Instead, Microsoft Edge’s Internet Explorer Legacy mode means that users can stay on one browser – to “seamlessly experience the best of the modern web in one tab while accessing a business-critical legacy IE 11 app in another tab”, the company says.
[Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids (now for v2!)
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
This might be related:
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
Technically, yes. However, no version prior to IE11 is supported. Nor is it recommended by Microsoft to my knowledge. I wouldn't personally put any work in to supporting anything other than IE11. And even then, soon the WebView2 control will be GA and you can ship the Edge (Chromium) RunTime installer with your application which installs the runtime in the background for your app to use. And Edge is supposed to be usable all the way back to Windows 7.
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
Hi, all.
No body mentions about how to create an additional gui using neutron. Let say I want to create a custom messagebox that popup as a neutron webapp. Is anyone know how to do that. The code seem to crash when I try to create a new Neutron object.
Thanks!
No body mentions about how to create an additional gui using neutron. Let say I want to create a custom messagebox that popup as a neutron webapp. Is anyone know how to do that. The code seem to crash when I try to create a new Neutron object.
Thanks!
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
This seems to work:
Code: Select all
neutron := new NeutronWindow()
; neutron.load("html\index.html")
neutron.Show("w2080 h1000")
neutron.Maximize()
neutron2 := new NeutronWindow()
; neutron2.load("html\index.html")
neutron2.Show("w2080 h1000")
neutron2.Maximize()
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
Thanks @Chunjee for the reply!
I put it in a function:
...and call it in HTML
it seem to crashes my program right away after clicking the button?
Any idea why?
Thanks!
I put it in a function:
Code: Select all
HtmlMsgBox(Options := "", Title := "", Text := "", Timeout := 0) {
NeutronMsgBox := new NeutronWindow()
NeutronMsgBox.Load("html_msgbox.html")
NeutronMsgBox.Gui("-Resize +LabelHtmlMsgBox")
NeutronMsgBox.Show("")
Return
NeutronMsgBoxClose:
NeutronMsgBox.Destroy() ;Free memory
Return
}
Code: Select all
TestBttn(neutron, event) {
HtmlMsgBox("", "Test Msgbox")
}
Code: Select all
<button id="test-btn" type="button" class="btn btn-primary btn-xs" onclick="ahk.TestBttn(event)">Test MsgBox</button>
Any idea why?
Thanks!
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
Hi all,
Anyone know how to stop the mouse cursor to change to "resize-icon" when hover the edges of the window? I made an app that do not resize window, so it doesn't make sense when hover the edges of the window and cursor changed to resize-icon.
Thanks!
Anyone know how to stop the mouse cursor to change to "resize-icon" when hover the edges of the window? I made an app that do not resize window, so it doesn't make sense when hover the edges of the window and cursor changed to resize-icon.
Thanks!
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
@KiddoV
It is probably possible but why? There's nothing wrong with letting it resize since the browser should handle resizing any UI elements for you.
It is probably possible but why? There's nothing wrong with letting it resize since the browser should handle resizing any UI elements for you.
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
I've picked up on your work with WebView and managed to backport it to AHKv1, as well as solved a few of the problems that you were facing with, for example, AddHostObjectToScript and reading object properties (AHK's IDispatch implementation and WebView2's IDispatch implementation are both quirky, and in a way that conflicts. I had to rebuild the IDispatch support from the ground up in AHK). I don't have the code posted anywhere outside of Discord, but it might make its way online soon so keep an eye out. It looks like the WebView2 control is more usable in v2 and v1 thanks to anonymous functions, but the unique way in which Microsoft implement things like thread locking and callbacks mean that it will likely never be as easy to use as IE11/ActiveX/Neutron.kczx3 wrote: ↑24 Aug 2020, 11:21Technically, yes. However, no version prior to IE11 is supported. Nor is it recommended by Microsoft to my knowledge. I wouldn't personally put any work in to supporting anything other than IE11. And even then, soon the WebView2 control will be GA and you can ship the Edge (Chromium) RunTime installer with your application which installs the runtime in the background for your app to use. And Edge is supposed to be usable all the way back to Windows 7.
Also, to anyone who is concerned about IE disappearing from the OS--don't be too concerned. The component that Edge will use to display IE content in Edge is, as far as I am aware, the same component that is used by Neutron. As long as Edge retains IE backward compatibility Neutron should still work fine.
One of the first things that was brought to my attention after releasing Neutron was the fact that multiple-window support was broken. It turned out to be an easy fix ( https://github.com/G33kDude/Neutron.ahk/commit/63a0785d140202eb013226afd84da65bc19a56ca ) but it hasn't yet made its way to a release. Time constraints and other commitments have kept me from doing it justice. Either implement that small patch yourself, or grab the latest development copy instead of the release build: https://github.com/G33kDude/Neutron.ahk/blob/master/Neutron.ahkKiddoV wrote: it seem to crashes my program right away after clicking the button?
Any idea why?
Thanks!
This was a feature that I neglected for release 1.0.0. Right now, my best recommendation would be to set a minimum size and, if you really need to, a maximum size that the window should be. It's 2020, windows should be resizable. That said, if you really do need to get rid of resizing altogether you can comment out the contents of the if statement where it says if (Msg == this.WM_NCHITTEST) in the _WindowProc(Msg, wParam, lParam) method.KiddoV wrote: Hi all,
Anyone know how to stop the mouse cursor to change to "resize-icon" when hover the edges of the window? I made an app that do not resize window, so it doesn't make sense when hover the edges of the window and cursor changed to resize-icon.
Thanks!
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
Thank you @GeekDude. Really love your work!
Do you think if it is possible to make a Neutron library (maybe in the future) that won't need IE in the window system?. I mean to make a stand-alone Neutron lib that does not depend on IE browser.
Do you think if it is possible to make a Neutron library (maybe in the future) that won't need IE in the window system?. I mean to make a stand-alone Neutron lib that does not depend on IE browser.
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
@GeekDude
Glad that my efforts (that were only possible due to the efforts by @Flipeador) helped you to pick up and continue with it. I find most tasks are easier with AHK v2 due to GUI objects and fat-arrow functions (scope inheritance!). That said, I agree that WebView2 will never be as simple as the Web Browser control because WebView2 doesn't expose the DOM at all. Everything must be handled by messaging to my knowledge. I think its worth it though considering how much better of a browser and JavaScript environment that WebView2 gives.
I didn't explicitly catch this but are you backporting it to v1 to then use with Neutron?
Glad that my efforts (that were only possible due to the efforts by @Flipeador) helped you to pick up and continue with it. I find most tasks are easier with AHK v2 due to GUI objects and fat-arrow functions (scope inheritance!). That said, I agree that WebView2 will never be as simple as the Web Browser control because WebView2 doesn't expose the DOM at all. Everything must be handled by messaging to my knowledge. I think its worth it though considering how much better of a browser and JavaScript environment that WebView2 gives.
I didn't explicitly catch this but are you backporting it to v1 to then use with Neutron?
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
Not Neutron, but later libraries that take advantage of Edge's upcoming desktop app integration API won't need IE (they'll need Edge )
I haven't used v2 at all, and I think more people find my libraries more useful as v1 compatible than as v2 compatible. I started with WebView2 in v1 before I saw any of your/@Flipeador/others' work on it, but wasn't able to get it to work until I started comparing my implementation against the v2 code all of you had provided. The v2 implementation is much simpler than v1, so long-term I think it will be more attractive to move over to v2.kczx3 wrote: @GeekDude
Glad that my efforts (that were only possible due to the efforts by @Flipeador) helped you to pick up and continue with it. I find most tasks are easier with AHK v2 due to GUI objects and fat-arrow functions (scope inheritance!). That said, I agree that WebView2 will never be as simple as the Web Browser control because WebView2 doesn't expose the DOM at all. Everything must be handled by messaging to my knowledge. I think its worth it though considering how much better of a browser and JavaScript environment that WebView2 gives.
I didn't explicitly catch this but are you backporting it to v1 to then use with Neutron?
WebView2 won't ever make it to Neutron simply because its core behavior is fundamentally different, but I've been thinking about how I could best go about creating a similar library for WebView2. It will probably be called Positron (if it ever sees daylight).
Also, it does kind of expose the DOM through the CallDevToolsProtocolMethod (DOM endpoints are available for that) but it's much more complicated than just invoking JavaScript and, as all calls use serialized IPC, not significantly different than invoking JS. Maybe I can wrap that in a way that makes sense, but I'm not sure the effort is warranted.
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
@GeekDude be careful! Once you start using v2 you might not go back!
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
@GeekDude ,
@ I am looking forward to see the future of Neutron on Edge. In my opinion tho, I would rather implement it into Chrome (If that possible) . What do you think?
@ Maybe it just me who cares so much about the UI. But, do you know how to change the scroll bar outlook? It looks so ugly and cannot customize on IE11. Is there a way to customize it either on HTML/CSS side or AHK side?
@ I am looking forward to see the future of Neutron on Edge. In my opinion tho, I would rather implement it into Chrome (If that possible) . What do you think?
@ Maybe it just me who cares so much about the UI. But, do you know how to change the scroll bar outlook? It looks so ugly and cannot customize on IE11. Is there a way to customize it either on HTML/CSS side or AHK side?
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
@GeekDude
Hi GeekDude, I like Neutron very much.
I am trying to use Neutron to create a simple project.
I have encountered some problems, I would like to ask you for advice.
1
I created two files: test.ahk, test.html
There is only one input box in test.html, and there is a piece of js code to capture the keyup event.
Capture keyup events, pop-up prompt:
If I open test.html with a browser, the keyup event can be captured in Chrome, IE, and Edge browsers.
But when test.html is loaded with Neutron in test.ahk, the keyup event cannot be captured.
If I replace keyup with focus, mouseup, mousedown events, they can be captured normally.
Further testing found that when the input method is switched to non-English, the a-z keys can be captured,
but the number keys cannot be captured.
If I change keyup to keydown, the number keys can be captured, but the a-z keys cannot be captured.
When the input method is switched to non-English, the a-z keys can be captured.
Add onkeydown="ahk.keyup(event)" directly to <input/>, the result is the same.
test.ahk:
test.html:
2
In addition, I want to drag the entire window when dragging the input box with the mouse,
so I added the DragInputBox function under the Neutron.ahk: DragTitleBar function.
and set "onmousedown" to neutron.DragInputBox()
After releasing the input box, I can immediately press the keyboard to enter characters.
If I do not enter the characters immediately, but enter it after one second or two,
the edit box does not respond. I have to input only after moving the mouse slightly.
If I use PostMessage to move the window,
the problem is more serious: After dragging and releasing, I have to move the mouse to input characters.
DragInputBox:
Neutron.ahk:
3
I want to make buttons or other elements in the window can be dragged and sorted automatically.
I searched for some js and css scripts, but when the corresponding webpage is loaded with Neutron,
these elements cannot be dragged freely.
Browsing these web pages with a browser alone,
chrome and Microsoft Edge can access normally, and elements can be dragged.
Using Internet Explorer 11, elements cannot be dragged.
https ksylvest.github.io /jquery-gridly/ Broken Link for safety
https shopify.github.io /draggable/examples/flexbox.html Broken Link for safety
Internet Explorer 11 and Microsoft Edge:
My test steps:
Use chrome to browse https ksylvest.github.io /jquery-gridly/ Broken Link for safety , then ctrl+s to save the page.
Then use Neutron to load the saved webpage, js reports an error, and dragging has no effect.
In the webpage, I deleted the useless code, only kept the core code, and still can't drag.
What can I do to make Neutron load these pages successfully?
Browser used:
Chrome : 86.0.4240.183
Internet Explorer11 : 11.572.19041.0
Microsoft Edge : 86.0.622.63
Hi GeekDude, I like Neutron very much.
I am trying to use Neutron to create a simple project.
I have encountered some problems, I would like to ask you for advice.
1
I created two files: test.ahk, test.html
There is only one input box in test.html, and there is a piece of js code to capture the keyup event.
Capture keyup events, pop-up prompt:
If I open test.html with a browser, the keyup event can be captured in Chrome, IE, and Edge browsers.
But when test.html is loaded with Neutron in test.ahk, the keyup event cannot be captured.
If I replace keyup with focus, mouseup, mousedown events, they can be captured normally.
Further testing found that when the input method is switched to non-English, the a-z keys can be captured,
but the number keys cannot be captured.
If I change keyup to keydown, the number keys can be captured, but the a-z keys cannot be captured.
When the input method is switched to non-English, the a-z keys can be captured.
Add onkeydown="ahk.keyup(event)" directly to <input/>, the result is the same.
test.ahk:
Code: Select all
#SingleInstance, Force
#NoEnv
SetBatchLines, -1
#Include Neutron.ahk
neutron := new NeutronWindow()
neutron.Load("test.html")
neutron.Gui("+LabelNeutron")
neutron.Show("w500 h300")
return
NeutronClose:
ExitApp
return
keyup(neutron, event)
{
MsgBox,,,111,1
}
Code: Select all
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script type="text/javascript" charset="utf-8" src="https cdn.bootcss.com /jquery/2.1.0/jquery.min.js"></script> Broken Link for safety
<style type="text/css">
input.input_text{
width: 100%;
}
</style>
</head>
<body class="d-flex flex-column">
<div class="box">
<input type="text" class="input_text" onmousedown="neutron.DragInputBox()" id="searchInput" placeholder="">
</div>
</body>
</html>
<script>
$(document).ready(function(){
$("#searchInput").on('keyup', function() {
alert("hello world");
});
});
</script>
2
In addition, I want to drag the entire window when dragging the input box with the mouse,
so I added the DragInputBox function under the Neutron.ahk: DragTitleBar function.
and set "onmousedown" to neutron.DragInputBox()
After releasing the input box, I can immediately press the keyboard to enter characters.
If I do not enter the characters immediately, but enter it after one second or two,
the edit box does not respond. I have to input only after moving the mouse slightly.
If I use PostMessage to move the window,
the problem is more serious: After dragging and releasing, I have to move the mouse to input characters.
DragInputBox:
Code: Select all
DragInputBox()
{
CoordMode, Mouse, Window
MouseGetPos, mX_win, mY_win
if(mX_win>A_CaretX+10)
{
;PostMessage, this.WM_NCLBUTTONDOWN, 2, 0,, % "ahk_id" this.hWnd
SetWinDelay,10
CoordMode,Mouse
MouseGetPos,KDE_X1,KDE_Y1,KDE_id
WinGet,KDE_Win,MinMax,ahk_id %KDE_id%
If KDE_Win
return
; Get the initial window position.
WinGetPos,KDE_WinX1,KDE_WinY1,,,ahk_id %KDE_id%
Loop
{
GetKeyState,KDE_Button,LButton,P ; If the button has been released, exit.
If KDE_Button = U
break
MouseGetPos,KDE_X2,KDE_Y2 ; Get the current mouse position.
KDE_X2 -= KDE_X1 ; Get the offset from the original mouse position.
KDE_Y2 -= KDE_Y1
KDE_WinX2 := (KDE_WinX1 + KDE_X2) ; Apply this offset to the window position.
KDE_WinY2 := (KDE_WinY1 + KDE_Y2)
WinMove,ahk_id %KDE_id%,,%KDE_WinX2%,%KDE_WinY2% ; Move the window to a new position.
}
}
}
Code: Select all
;
; Neutron.ahk v1.0.0
; Copyright (c) 2020 Philip Taylor (known also as GeekDude, G33kDude)
; https://github.com/G33kDude/Neutron.ahk
;
; MIT License
;
; Permission is hereby granted, free of charge, to any person obtaining a copy
; of this software and associated documentation files (the "Software"), to deal
; in the Software without restriction, including without limitation the rights
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
; copies of the Software, and to permit persons to whom the Software is
; furnished to do so, subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in all
; copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
; SOFTWARE.
;
class NeutronWindow
{
static TEMPLATE := "
( ; html
<!DOCTYPE html><html>
<head>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<style>
html, body {
width: 100%; height: 100%;
margin: 0; padding: 0;
font-family: sans-serif;
}
body {
display: flex;
flex-direction: column;
}
header {
width: 100%;
display: flex;
background: silver;
font-family: Segoe UI;
font-size: 9pt;
}
.title-bar {
padding: 0.35em 0.5em;
flex-grow: 1;
}
.title-btn {
padding: 0.35em 1.0em;
cursor: pointer;
vertical-align: bottom;
font-family: Webdings;
font-size: 11pt;
}
.title-btn:hover {
background: rgba(0, 0, 0, .2);
}
.title-btn-close:hover {
background: #dc3545;
}
.main {
flex-grow: 1;
padding: 0.5em;
overflow: auto;
}
</style>
<style>{}</style>
</head>
<body>
<header>
<span class='title-bar' onmousedown='neutron.DragTitleBar()'>{}</span>
<span class='title-btn' onclick='neutron.Minimize()'>0</span>
<span class='title-btn' onclick='neutron.Maximize()'>1</span>
<span class='title-btn title-btn-close' onclick='neutron.Close()'>r</span>
</header>
<div class='main'>{}</div>
<script>{}</script>
</body>
</html>
)"
; --- Constants ---
static VERSION := "1.0.0"
; Windows Messages
, WM_DESTROY := 0x02
, WM_SIZE := 0x05
, WM_NCCALCSIZE := 0x83
, WM_NCHITTEST := 0x84
, WM_NCLBUTTONDOWN := 0xA1
, WM_KEYDOWN := 0x100
, WM_MOUSEMOVE := 0x200
, WM_LBUTTONDOWN := 0x201
; Non-client hit test values (WM_NCHITTEST)
, HT_VALUES := [[13, 12, 14], [10, 1, 11], [16, 15, 17]]
; Registry keys
, KEY_FBE := "HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MAIN"
. "\FeatureControl\FEATURE_BROWSER_EMULATION"
; Undoucmented Accent API constants
; https withinrafael.com /2018/02/02/adding-acrylic-blur-to-your-windows-10-apps-redstone-4-desktop-apps/ Broken Link for safety
, ACCENT_ENABLE_BLURBEHIND := 3
, WCA_ACCENT_POLICY := 19
; Other constants
, EXE_NAME := A_IsCompiled ? A_ScriptName : StrSplit(A_AhkPath, "\").Pop()
; --- Instance Variables ---
; Maximum pixel inset for sizing handles to appear
border_size := 6
; The window size
w := 800
h := 600
; --- Properties ---
; Get the JS DOM object
doc[]
{
get
{
return this.wb.Document
}
}
; Get the JS Window object
wnd[]
{
get
{
return this.wb.Document.parentWindow
}
}
; --- Construction, Destruction, Meta-Functions ---
__New(html:="", css:="", js:="", title:="Neutron")
{
static wb
this.LISTENERS := [this.WM_DESTROY, this.WM_SIZE, this.WM_NCCALCSIZE
, this.WM_KEYDOWN, this.WM_LBUTTONDOWN]
; Create necessary circular references
this.bound := {}
this.bound._OnMessage := this._OnMessage.Bind(this)
; Bind message handlers
for i, message in this.LISTENERS
OnMessage(message, this.bound._OnMessage)
; Create and save the GUI
; TODO: Restore previous default GUI
Gui, New, +hWndhWnd +Resize -DPIScale
this.hWnd := hWnd
; Enable shadow
VarSetCapacity(margins, 16, 0)
NumPut(1, &margins, 0, "Int")
DllCall("Dwmapi\DwmExtendFrameIntoClientArea"
, "UPtr", hWnd ; HWND hWnd
, "UPtr", &margins) ; MARGINS *pMarInset
; When manually resizing a window, the contents of the window often "lag
; behind" the new window boundaries. Until they catch up, Windows will
; render the border and default window color to fill that area. On most
; windows this will cause no issue, but for borderless windows this can
; cause rendering artifacts such as thin borders or unwanted colors to
; appear in that area until the rest of the window catches up.
;
; When creating a dark-themed application, these artifacts can cause
; jarringly visible bright areas. This can be mitigated some by changing
; the window settings to cause dark/black artifacts, but it's not a
; generalizable approach, so if I were to do that here it could cause
; issues with light-themed apps.
;
; Some borderless window libraries, such as rossy's C implementation
; (https://github.com/rossy/borderless-window) hide these artifacts by
; playing with the window transparency settings which make them go away
; but also makes it impossible to show certain colors (in rossy's case,
; Fuchsia/FF00FF).
;
; Luckly, there's an undocumented Windows API function in user32.dll
; called SetWindowCompositionAttribute, which allows you to change the
; window accenting policies. This tells the DWM compositor how to fill
; in areas that aren't covered by controls. By enabling the "blurbehind"
; accent policy, Windows will render a blurred version of the screen
; contents behind your window in that area, which will not be visually
; jarring regardless of the colors of your application or those behind
; it.
;
; Because this API is undocumented (and unavailable in Windows versions
; below 10) it's not a one-size-fits-all solution, and could break with
; future system updates. Hopefully a better soultion for the problem
; this hack addresses can be found for future releases of this library.
;
; https withinrafael.com /2018/02/02/adding-acrylic-blur-to-your-windows-10-apps-redstone-4-desktop-apps/ Broken Link for safety
; https://github.com/melak47/BorderlessWindow/issues/13#issuecomment-309154142
; http undoc.airesoft.co.uk /user32.dll/SetWindowCompositionAttribute.php Broken Link for safety
; https gist.github.com /riverar/fd6525579d6bbafc6e48 Broken Link for safety
; https vhanla.codigobit.info /2015/07/enable-windows-10-aero-glass-aka-blur.html Broken Link for safety
Gui, Color, 0, 0
VarSetCapacity(wcad, A_PtrSize+A_PtrSize+4, 0)
NumPut(this.WCA_ACCENT_POLICY, &wcad, 0, "Int")
VarSetCapacity(accent, 16, 0)
NumPut(this.ACCENT_ENABLE_BLURBEHIND, &accent, 0, "Int")
NumPut(&accent, &wcad, A_PtrSize, "Ptr")
NumPut(16, &wcad, A_PtrSize+A_PtrSize, "Int")
DllCall("SetWindowCompositionAttribute", "UPtr", hWnd, "UPtr", &wcad)
; Creating an ActiveX control with a valid URL instantiates a
; WebBrowser, saving its object to the associated variable. The "about"
; URL scheme allows us to start the control on either a blank page, or a
; page with some HTML content pre-loaded by passing HTML after the
; colon: "about:<!DOCTYPE html><body>...</body>"
; Read more about the WebBrowser control here:
; http msdn.microsoft.com /en-us/library/aa752085 Broken Link for safety
; For backwards compatibility reasons, the WebBrowser control defaults
; to IE7 emulation mode. The standard method of mitigating this is to
; include a compatibility meta tag in the HTML, but this requires
; tampering to the HTML and does not solve all compatibility issues.
; By tweaking the registry before and after creation of the control we
; can opt-out of the browser emulation feature altogether with minimal
; impact on the rest of the system.
; Read more about browser compatibility modes here:
; https://docs.microsoft.com/en-us/archive/blogs/patricka/controlling-webbrowser-control-compatibility
RegRead, fbe, % this.KEY_FBE, % this.EXE_NAME
RegWrite, REG_DWORD, % this.KEY_FBE, % this.EXE_NAME, 0
Gui, Add, ActiveX, vwb hWndhWB x0 y0 w800 h600, about:blank
if (fbe = "")
RegDelete, % this.KEY_FBE, % this.EXE_NAME
else
RegWrite, REG_DWORD, % this.KEY_FBE, % this.EXE_NAME, % fbe
; Save the WebBrowser control to reference later
this.wb := wb
this.hWB := hWB
; Connect the web browser's event stream to a new event handler object
ComObjConnect(this.wb, new this.WBEvents(this))
; Compute the HTML template if necessary
if !(html ~= "i)^<!DOCTYPE")
html := Format(this.TEMPLATE, css, title, html, js)
; Write the given content to the page
this.doc.write(html)
this.doc.close()
; Inject the AHK objects into the JS scope
this.wnd.neutron := this
this.wnd.ahk := new this.Dispatch(this)
; Wait for the page to finish loading
while wb.readyState < 4
Sleep, 50
; Subclass the rendered Internet Explorer_Server control to intercept
; its events, including WM_NCHITTEST and WM_NCLBUTTONDOWN.
; Read more here: https forum.juce.com /t/_/27937 Broken Link for safety
; And in the AutoHotkey documentation for RegisterCallback (Example 2)
dhw := A_DetectHiddenWindows
DetectHiddenWindows, On
ControlGet, hWnd, hWnd,, Internet Explorer_Server1, % "ahk_id" this.hWnd
this.hIES := hWnd
DetectHiddenWindows, %dhw%
this.pWndProc := RegisterCallback(this._WindowProc, "", 4, &this)
this.pWndProcOld := DllCall("SetWindowLong" (A_PtrSize == 8 ? "Ptr" : "")
, "Ptr", hWnd ; HWND hWnd
, "Int", -4 ; int nIndex (GWLP_WNDPROC)
, "Ptr", this.pWndProc ; LONG_PTR dwNewLong
, "Ptr") ; LONG_PTR
; Stop the WebBrowser control from consuming file drag and drop events
this.wb.RegisterAsDropTarget := False
DllCall("ole32\RevokeDragDrop", "UPtr", this.hIES)
}
; Show an alert for debugging purposes when the class gets garbage collected
; __Delete()
; {
; MsgBox, __Delete
; }
; --- Event Handlers ---
_OnMessage(wParam, lParam, Msg, hWnd)
{
if (hWnd == this.hWnd)
{
; Handle messages for the main window
if (Msg == this.WM_NCCALCSIZE)
{
; Size the client area to fill the entire window.
; See this project for more information:
; https://github.com/rossy/borderless-window
; Fill client area when not maximized
if !DllCall("IsZoomed", "UPtr", hWnd)
return 0
; else crop borders to prevent screen overhang
; Query for the window's border size
VarSetCapacity(windowinfo, 60, 0)
NumPut(60, windowinfo, 0, "UInt")
DllCall("GetWindowInfo", "UPtr", hWnd, "UPtr", &windowinfo)
cxWindowBorders := NumGet(windowinfo, 48, "Int")
cyWindowBorders := NumGet(windowinfo, 52, "Int")
; Inset the client rect by the border size
NumPut(NumGet(lParam+0, "Int") + cxWindowBorders, lParam+0, "Int")
NumPut(NumGet(lParam+4, "Int") + cyWindowBorders, lParam+4, "Int")
NumPut(NumGet(lParam+8, "Int") - cxWindowBorders, lParam+8, "Int")
NumPut(NumGet(lParam+12, "Int") - cyWindowBorders, lParam+12, "Int")
return 0
}
else if (Msg == this.WM_SIZE)
{
; Extract size from LOWORD and HIWORD (preserving sign)
this.w := w := lParam<<48>>48
this.h := h := lParam<<32>>48
DllCall("MoveWindow", "UPtr", this.hWB, "Int", 0, "Int", 0, "Int", w, "Int", h, "UInt", 0)
return 0
}
else if (Msg == this.WM_DESTROY)
{
; Clean up all our circular references so that the object may be
; garbage collected.
for i, message in this.LISTENERS
OnMessage(message, this.bound._OnMessage, 0)
this.bound := []
}
}
else if (hWnd == this.hIES)
{
; Handle messages for the rendered Internet Explorer_Server
if (Msg == this.WM_KEYDOWN)
{
; Accelerator handling code from AutoHotkey Installer
if (Chr(wParam) ~= "[A-Z]" || wParam = 0x74) ; Disable Ctrl+O/L/F/N and F5.
return
Gui +OwnDialogs ; For threadless callbacks which interrupt this.
pipa := ComObjQuery(this.wb, "{00000117-0000-0000-C000-000000000046}")
VarSetCapacity(kMsg, 48), NumPut(A_GuiY, NumPut(A_GuiX
, NumPut(A_EventInfo, NumPut(lParam, NumPut(wParam
, NumPut(Msg, NumPut(hWnd, kMsg)))), "uint"), "int"), "int")
Loop 2
r := DllCall(NumGet(NumGet(1*pipa)+5*A_PtrSize), "ptr", pipa, "ptr", &kMsg)
; Loop to work around an odd tabbing issue (it's as if there
; is a non-existent element at the end of the tab order).
until wParam != 9 || this.wb.document.activeElement != ""
ObjRelease(pipa)
if r = 0 ; S_OK: the message was translated to an accelerator.
return 0
return
}
}
}
_WindowProc(Msg, wParam, lParam)
{
Critical
hWnd := this
this := Object(A_EventInfo)
if (Msg == this.WM_NCHITTEST)
{
; Check to see if the cursor is near the window border, which
; should be treated as the "non-client" drag-to-resize area.
; https://autohotkey.com/board/topic/23969-/#entry155480
; Extract coordinates from LOWORD and HIWORD (preserving sign)
x := lParam<<48>>48, y := lParam<<32>>48
; Get the window position for comparison
WinGetPos, wX, wY, wW, wH, % "ahk_id" this.hWnd
; Calculate positions in the lookup tables
row := (x < wX + this.BORDER_SIZE) ? 1 : (x >= wX + wW - this.BORDER_SIZE) ? 3 : 2
col := (y < wY + this.BORDER_SIZE) ? 1 : (y >= wY + wH - this.BORDER_SIZE) ? 3 : 2
return this.HT_VALUES[col, row]
}
else if (Msg == this.WM_NCLBUTTONDOWN)
{
; Hoist nonclient clicks to main window
return DllCall("SendMessage", "Ptr", this.hWnd, "UInt", Msg, "UPtr", wParam, "Ptr", lParam, "Ptr")
}
; Otherwise (since above didn't return), pass all unhandled events to the original WindowProc.
return DllCall("CallWindowProc"
, "Ptr", this.pWndProcOld ; WNDPROC lpPrevWndFunc
, "Ptr", hWnd ; HWND hWnd
, "UInt", Msg ; UINT Msg
, "UPtr", wParam ; WPARAM wParam
, "Ptr", lParam ; LPARAM lParam
, "Ptr") ; LRESULT
}
; --- Instance Methods ---
; Triggers window dragging. Call this on mouse click down. Best used as your
; title bar's onmousedown attribute.
DragTitleBar()
{
PostMessage, this.WM_NCLBUTTONDOWN, 2, 0,, % "ahk_id" this.hWnd
}
DragInputBox()
{
CoordMode, Mouse, Window
MouseGetPos, mX_win, mY_win
if(mX_win>A_CaretX+10)
{
;PostMessage, this.WM_NCLBUTTONDOWN, 2, 0,, % "ahk_id" this.hWnd
SetWinDelay,10
CoordMode,Mouse
MouseGetPos,KDE_X1,KDE_Y1,KDE_id
WinGet,KDE_Win,MinMax,ahk_id %KDE_id%
If KDE_Win
return
; Get the initial window position.
WinGetPos,KDE_WinX1,KDE_WinY1,,,ahk_id %KDE_id%
Loop
{
GetKeyState,KDE_Button,LButton,P ; If the button has been released, exit.
If KDE_Button = U
break
MouseGetPos,KDE_X2,KDE_Y2 ; Get the current mouse position.
KDE_X2 -= KDE_X1 ; Get the offset from the original mouse position.
KDE_Y2 -= KDE_Y1
KDE_WinX2 := (KDE_WinX1 + KDE_X2) ; Apply this offset to the window position.
KDE_WinY2 := (KDE_WinY1 + KDE_Y2)
WinMove,ahk_id %KDE_id%,,%KDE_WinX2%,%KDE_WinY2% ; Move the window to a new position.
}
}
}
; Minimizes the Neutron window. Best used in your title bar's minimize
; button's onclick attribute.
Minimize()
{
Gui, % this.hWnd ":Minimize"
}
; Maximize the Neutron window. Best used in your title bar's maximize
; button's onclick attribute.
Maximize()
{
if DllCall("IsZoomed", "UPtr", this.hWnd)
Gui, % this.hWnd ":Restore"
else
Gui, % this.hWnd ":Maximize"
}
; Closes the Neutron window. Best used in your title bar's close
; button's onclick attribute.
Close()
{
WinClose, % "ahk_id" this.hWnd
}
; Hides the Nuetron window.
Hide()
{
Gui, % this.hWnd ":Hide"
}
; Destroys the Neutron window. Do this when you would no longer want to
; re-show the window, as it will free the memory taken up by the GUI and
; ActiveX control. This method is best used either as your title bar's close
; button's onclick attribute, or in a custom window close routine.
Destroy()
{
Gui, % this.hWnd ":Destroy"
}
; Shows a hidden Neutron window.
Show(options:="")
{
w := RegExMatch(options, "w\s*\K\d+", match) ? match : this.w
h := RegExMatch(options, "h\s*\K\d+", match) ? match : this.h
; AutoHotkey sizes the window incorrectly, trying to account for borders
; that aren't actually there. Call the function AHK uses to offset and
; apply the change in reverse to get the actual wanted size.
VarSetCapacity(rect, 16, 0)
DllCall("AdjustWindowRectEx"
, "Ptr", &rect ; LPRECT lpRect
, "UInt", 0x80CE0000 ; DWORD dwStyle
, "UInt", 0 ; BOOL bMenu
, "UInt", 0 ; DWORD dwExStyle
, "UInt") ; BOOL
w += NumGet(&rect, 0, "Int")-NumGet(&rect, 8, "Int")
h += NumGet(&rect, 4, "Int")-NumGet(&rect, 12, "Int")
Gui, % this.hWnd ":Show", %options% w%w% h%h%
}
; Loads an HTML file by name (not path). When running the script uncompiled,
; looks for the file in the local directory. When running the script
; compiled, looks for the file in the EXE's RCDATA. Files included in your
; compiled EXE by FileInstall are stored in RCDATA whether they get
; extracted or not. An easy way to get your Neutron resources into a
; compiled script, then, is to put FileInstall commands for them right below
; the return at the bottom of your AutoExecute section.
;
; Parameters:
; fileName - The name of the HTML file to load into the Neutron window.
; Make sure to give just the file name, not the full path.
;
; Returns: nothing
;
; Example:
;
; ; AutoExecute Section
; neutron := new NeutronWindow()
; neutron.Load("index.html")
; neutron.Show()
; return
; FileInstall, index.html, index.html
; FileInstall, index.css, index.css
;
Load(fileName)
{
; Complete the path based on compiled state
if A_IsCompiled
url := "res://" this.wnd.encodeURIComponent(A_ScriptFullPath) "/10/" fileName
else
url := A_WorkingDir "/" fileName
; Navigate to the calculated file URL
this.wb.Navigate(url)
; Wait for the page to finish loading
while this.wb.readyState < 3
Sleep, 50
; Inject the AHK objects into the JS scope
this.wnd.neutron := this
this.wnd.ahk := new this.Dispatch(this)
; Wait for the page to finish loading
while this.wb.readyState < 4
Sleep, 50
}
; Shorthand method for document.querySelector
qs(selector)
{
return this.doc.querySelector(selector)
}
; Shorthand method for document.querySelectorAll
qsa(selector)
{
return this.doc.querySelectorAll(selector)
}
; Passthrough method for the Gui command, targeted at the Neutron Window
; instance
Gui(subCommand, value1:="", value2:="", value3:="")
{
Gui, % this.hWnd ":" subCommand, %value1%, %value2%, %value3%
}
; --- Static Methods ---
; Given an HTML Collection (or other JavaScript array), return an enumerator
; that will iterate over its items.
;
; Parameters:
; htmlCollection - The JavaScript array to be iterated over
;
; Returns: An Enumerable object
;
; Example:
;
; neutron := new NeutronWindow("<body><p>A</p><p>B</p><p>C</p></body>")
; neutron.Show()
; for i, element in neutron.Each(neutron.body.children)
; MsgBox, % i ": " element.innerText
;
Each(htmlCollection)
{
return new this.Enumerable(htmlCollection)
}
; Given an HTML Form Element, construct a FormData object
;
; Parameters:
; formElement - The HTML Form Element
; useIdAsName - When a field's name is blank, use it's ID instead
;
; Returns: A FormData object
;
; Example:
;
; neutron := new NeutronWindow("<form>"
; . "<input type='text' name='field1' value='One'>"
; . "<input type='text' name='field2' value='Two'>"
; . "<input type='text' name='field3' value='Three'>"
; . "</form>")
; neutron.Show()
; formElement := neutron.doc.querySelector("form") ; Grab 1st form on page
; formData := neutron.GetFormData(formElement) ; Get form data
; MsgBox, % formData.field2 ; Pull a single field
; for name, element in formData ; Iterate all fields
; MsgBox, %name%: %element%
;
GetFormData(formElement, useIdAsName:=True)
{
formData := new this.FormData()
for i, field in this.Each(formElement.elements)
{
; Discover the field's name
name := ""
try ; fieldset elements error when reading the name field
name := field.name
if (name == "" && useIdAsName)
name := field.id
; Filter against fields which should be omitted
if (name == "" || field.disabled
|| field.type ~= "^file|reset|submit|button$")
continue
; Handle select-multiple variants
if (field.type == "select-multiple")
{
for j, option in this.Each(field.options)
if (option.selected)
formData.add(name, option.value)
continue
}
; Filter against unchecked checkboxes and radios
if (field.type ~= "^checkbox|radio$" && !field.checked)
continue
; Return the field values
formData.add(name, field.value)
}
return formData
}
; Given a potentially HTML-unsafe string, return an HTML safe string
; https://stackoverflow.com/a/6234804
EscapeHTML(unsafe)
{
unsafe := StrReplace(unsafe, "&", "&")
unsafe := StrReplace(unsafe, "<", "<")
unsafe := StrReplace(unsafe, ">", ">")
unsafe := StrReplace(unsafe, """", """)
unsafe := StrReplace(unsafe, "''", "'")
return unsafe
}
; Wrapper for Format that applies EscapeHTML to each value before passing
; them on. Useful for dynamic HTML generation.
FormatHTML(formatStr, values*)
{
for i, value in values
values[i] := this.EscapeHTML(value)
return Format(formatStr, values*)
}
; --- Nested Classes ---
; Proxies method calls to AHK function calls, binding a given value to the
; first parameter of the target function.
;
; For internal use only.
;
; Parameters:
; parent - The value to bind
;
class Dispatch
{
__New(parent)
{
this.parent := parent
}
__Call(params*)
{
; Make sure the given name is a function
if !(fn := Func(params[1]))
throw Exception("Unknown function: " params[1])
; Make sure enough parameters were given
if (params.length() < fn.MinParams)
throw Exception("Too few parameters given to " fn.Name ": " params.length())
; Make sure too many parameters weren't given
if (params.length() > fn.MaxParams && !fn.IsVariadic)
throw Exception("Too many parameters given to " fn.Name ": " params.length())
; Change first parameter from the function name to the neutron instance
params[1] := this.parent
; Call the function
return fn.Call(params*)
}
}
; Handles Web Browser events
; https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa768283%28v%3dvs.85%29
;
; For internal use only
;
; Parameters:
; parent - An instance of the Neutron class
;
class WBEvents
{
__New(parent)
{
this.parent := parent
}
DocumentComplete(wb)
{
; Inject the AHK objects into the JS scope
wb.document.parentWindow.neutron := this.parent
wb.document.parentWindow.ahk := new this.parent.Dispatch(this.parent)
}
}
; Enumerator class that enumerates the items of an HTMLCollection (or other
; JavaScript array).
;
; Best accessed through the .Each() helper method.
;
; Parameters:
; htmlCollection - The HTMLCollection to be enumerated.
;
class Enumerable
{
i := 0
__New(htmlCollection)
{
this.collection := htmlCollection
}
_NewEnum()
{
return this
}
Next(ByRef i, ByRef elem)
{
if (this.i >= this.collection.length)
return False
i := this.i
elem := this.collection.item(this.i++)
return True
}
}
; A collection similar to an OrderedDict designed for holding form data.
; This collection allows duplicate keys and enumerates key value pairs in
; the order they were added.
class FormData
{
names := []
values := []
; Add a field to the FormData structure.
;
; Parameters:
; name - The form field name associated with the value
; value - The value of the form field
;
; Returns: Nothing
;
Add(name, value)
{
this.names.Push(name)
this.values.Push(value)
}
; Get an array of all values associated with a name.
;
; Parameters:
; name - The form field name associated with the values
;
; Returns: An array of values
;
; Example:
;
; fd := new NeutronWindow.FormData()
; fd.Add("foods", "hamburgers")
; fd.Add("foods", "hotdogs")
; fd.Add("foods", "pizza")
; fd.Add("colors", "red")
; fd.Add("colors", "green")
; fd.Add("colors", "blue")
; for i, food in fd.All("foods")
; out .= i ": " food "`n"
; MsgBox, %out%
;
All(name)
{
values := []
for i, v in this.names
if (v == name)
values.Push(this.values[i])
return values
}
; Meta-function to allow direct access of field values using either dot
; or bracket notation. Can retrieve the nth item associated with a given
; name by passing more than one value in when bracket notation.
;
; Example:
;
; fd := new NeutronWindow.FormData()
; fd.Add("foods", "hamburgers")
; fd.Add("foods", "hotdogs")
; MsgBox, % fd.foods ; hamburgers
; MsgBox, % fd["foods", 2] ; hotdogs
;
__Get(name, n := 1)
{
for i, v in this.names
if (v == name && !--n)
return this.values[i]
}
; Allow iteration in the order fields were added, instead of a normal
; object's alphanumeric order of iteration.
;
; Example:
;
; fd := new NeutronWindow.FormData()
; fd.Add("z", "3")
; fd.Add("y", "2")
; fd.Add("x", "1")
; for name, field in fd
; out .= name ": " field ","
; MsgBox, %out% ; z: 3, y: 2, x: 1
;
_NewEnum()
{
return {"i": 0, "base": this}
}
Next(ByRef name, ByRef value)
{
if (++this.i > this.names.length())
return False
name := this.names[this.i]
value := this.values[this.i]
return True
}
}
}
I want to make buttons or other elements in the window can be dragged and sorted automatically.
I searched for some js and css scripts, but when the corresponding webpage is loaded with Neutron,
these elements cannot be dragged freely.
Browsing these web pages with a browser alone,
chrome and Microsoft Edge can access normally, and elements can be dragged.
Using Internet Explorer 11, elements cannot be dragged.
https ksylvest.github.io /jquery-gridly/ Broken Link for safety
https shopify.github.io /draggable/examples/flexbox.html Broken Link for safety
Internet Explorer 11 and Microsoft Edge:
My test steps:
Use chrome to browse https ksylvest.github.io /jquery-gridly/ Broken Link for safety , then ctrl+s to save the page.
Then use Neutron to load the saved webpage, js reports an error, and dragging has no effect.
In the webpage, I deleted the useless code, only kept the core code, and still can't drag.
What can I do to make Neutron load these pages successfully?
Browser used:
Chrome : 86.0.4240.183
Internet Explorer11 : 11.572.19041.0
Microsoft Edge : 86.0.622.63
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
@GeekDude
Any chance we can get a "sneak peak" at the V1 backport of WebView2? I'd love to check it out, not quite ready to go AHKv2.
Any chance we can get a "sneak peak" at the V1 backport of WebView2? I'd love to check it out, not quite ready to go AHKv2.
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
How can I show the GUI controls (Minimize, Maximize, Close) without using HTML "fake" controls? Instead of loading custom HTML, I'm redirecting to an external website, and it removes the titlebar controls.
EDIT: Nevermind. Found it. OnMessage
EDIT: Nevermind. Found it. OnMessage
Last edited by TheDewd on 18 Nov 2020, 13:50, edited 8 times in total.
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
superb. hats off to lazy to do it myself
We are troubled on every side‚ yet not distressed; we are perplexed‚
but not in despair; Persecuted‚ but not forsaken; cast down‚ but not destroyed;
Telegram is the best way to reach me
https://t.me/ttnnkkrr
If you have forum suggestions please submit a
Check Out WebWriter
but not in despair; Persecuted‚ but not forsaken; cast down‚ but not destroyed;
Telegram is the best way to reach me
https://t.me/ttnnkkrr
If you have forum suggestions please submit a
Check Out WebWriter
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
Can I use Neutron to control Discord which is an Electron app?
I would like to have a quick way to switch from Push-to-talk to Voice Activity.
I would like to have a quick way to switch from Push-to-talk to Voice Activity.
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
why neutron does not display scroll bars on my web page, even though when the web page is opened using ActiveX, chrome and IE there is no scroll bar problem. however, when using the neutron, the scroll bar does not appear.
- Attachments
-
- Neutron
- 003.png (85.89 KiB) Viewed 6232 times
-
- IE or ActiveX
- 002.png (108.21 KiB) Viewed 6232 times
-
- Chrome
- 001.png (106.26 KiB) Viewed 6232 times
Re: [Library] Neutron.ahk - AutoHotkey Web GUIs on Steroids
Hi, everyone!
I am currently using CodeMirror plugin (codemirror.net/index.html) to make a simple text editor with Neutron (of course). All of the default shortcut keys like: Ctrl+A, Ctrl+C, Ctrl+Z... were working well when I opened html file via IE11, but when I used AHK (Neutron) to load html files, I was not be able to press all the shortcut keys. Any idea why this is happened?
Thanks all!
I am currently using CodeMirror plugin (codemirror.net/index.html) to make a simple text editor with Neutron (of course). All of the default shortcut keys like: Ctrl+A, Ctrl+C, Ctrl+Z... were working well when I opened html file via IE11, but when I used AHK (Neutron) to load html files, I was not be able to press all the shortcut keys. Any idea why this is happened?
Thanks all!
Return to “Scripts and Functions (v1)”
Who is online
Users browsing this forum: No registered users and 117 guests