http://autohotkey.com/board/topic/23969-resizable-window-border/?p=154997
That was all well and good until I began to experience the issue described here a bit further down the same page, where the one message getting missed caused a native-looking border to be drawn over top, which wouldn't go away until you either restarted or minimized/restored it, and it was happening often enough to be annoying.
Lexikos covered the outline of a potential solution in the following reply, which was enough to start with, but I didn't find any working examples online, so I gave it a shot myself.
This took quite a few hours, but hopefully someone finds it useful. You can make some pretty slick looking apps using the handful of tricks shown.
Code: Select all
#NoEnv
SetBatchLines, -1
OnMessage(0x20, "WM_SETCURSOR")
OnMessage(0x200, "WM_MOUSEMOVE")
OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x202, "WM_LBUTTONUP")
global gui_id
title := "Borderless Test GUI"
; Normally having -Caption set with +Resize will still show a thin border around the GUI, and a thicker border at the top
; the two values at the end enable doublebuffering, which tends to reduce flicker when updating GUI elements (i.e., resizing)
Gui, +Hwndgui_id -Caption -MaximizeBox +E0x02000000 +E0x00080000
Gui, Color, black, black
Gui, Font, cEEE8D5 s10 Bold, Segoe UI
Gui, Add, Text, xm, % title
Gui, Font, s12 Norm, Segoe MDL2 Assets
Gui, Add, Text, yp vminimizeBtn 0x100, % Chr(0xE921)
Gui, Add, Text, yp vcloseBtn gGuiClose, % Chr(0xE106)
Gui, Font, s1
Gui, Add, Text, y+m vtitlebarDiv x1 +0x5 ; useful as a titlebar divider
Gui, Font, s9, Segoe UI
Gui, Add, Text, xm y+m, Here's some test text
Gui, Add, Edit, w300 h300, Here's an edit control
Gui, Show, Autosize, % title
WinSet, Transparent, 200, % "ahk_id" gui_id
Return
GuiClose:
ExitApp
; Resizes the edit control and titlebar div, moves the
; minimize & close buttons to the right of the GUI
;
; Set to Critical to prevent an issue where sometimes
; part of the window can disappear if it sets the window
; region before all the controls are able to be drawn
; but it might slow things down if you're using a lot
; of controls with AutoXYWH() for instance.
GuiSize:
Critical
If ErrorLevel = 1
Return
WinGetPos, , , winW, winH, % "ahk_id" gui_id
Guicontrol, Move, titlebarDiv, % "w" winW
GuiControl, MoveDraw, minimizeBtn, % "x" winW - 55
GuiControl, MoveDraw, closeBtn, % "x" winW - 30
GuiControl, Move, Edit1, % "w" winW - 25 " h" winH - 80
WinSet, Region , % "0-0 R15-15 w" winW " h" winH
Return
WM_LBUTTONUP() {
global
If isResizing {
isResizing := 0
DllCall("ReleaseCapture")
Tooltip
}
}
WM_LBUTTONDOWN() {
global isResizing, resizeBorder
WinGetPos, winX, winY, winW, winH, % "ahk_id" gui_id
MouseGetPos, mouseX, mouseY
; Capture mouse if cursor is over the resize area
If (!isResizing && resizeBorder) {
isResizing := 1
DllCall("SetCapture", "UInt", gui_id)
}
If ( A_Gui && mouseY < 29 ) ; move window from titlebar area while menus are hidden
PostMessage, 0xA1, 2 ; 0xA1 = WM_NCLBUTTONDOWN
If (A_GuiControl = "minimizeBtn") ; Minimize whent the 'button' is clicked
WinMinimize, % "ahk_id" gui_id
}
WM_SETCURSOR() {
global resizeBorder
WinGetPos, , , winWidth, winHeight, % "ahk_id" gui_id
borderSize := 8
, cornerMargin := 10
, borderW := borderSize
, borderE := winWidth - borderSize
, borderN := borderSize
, borderS := winHeight - borderSize
, IDC_SIZENS := 32645
, IDC_SIZEWE := 32644
, IDC_SIZENWSE := 32642
, IDC_SIZENESW := 32643
CoordMode, Mouse, Client
MouseGetPos, mouseX, mouseY
Switch
{
Case (mouseX < borderW + cornerMargin && mouseY < borderN + cornerMargin) : Cursor := IDC_SIZENWSE, resizeBorder := "NW"
Case (mouseX < borderW + cornerMargin && mouseY > borderS - cornerMargin) : Cursor := IDC_SIZENESW, resizeBorder := "SW"
Case (mouseX > borderE - cornerMargin && mouseY < borderN + cornerMargin) : Cursor := IDC_SIZENESW, resizeBorder := "NE"
Case (mouseX > borderE - cornerMargin && mouseY > borderS - cornerMargin) : Cursor := IDC_SIZENWSE, resizeBorder := "SE"
Case (mouseX < borderW) : Cursor := IDC_SIZEWE, resizeBorder := "W"
Case (mouseX > borderE) : Cursor := IDC_SIZEWE, resizeBorder := "E"
Case (mouseY > borderS) : Cursor := IDC_SIZENS, resizeBorder := "S"
Case (mouseY < borderN) : Cursor := IDC_SIZENS, resizeBorder := "N"
Default: Cursor := "", resizeBorder := ""
}
If (Cursor) {
CursorHandle := DllCall("LoadCursor", "ptr", 0, "ptr", Cursor, "ptr")
LastCursor := DllCall("SetCursor", "uint", CursorHandle)
Return true
} Else If (CursorHandle <> LastCursor) {
CursorHandle := DllCall("SetCursor", "uint", LastCursor)
Return true
} Else return
}
WM_MOUSEMOVE() {
global resizeBorder, isResizing
WinGetPos, winX, winY, winWidth, winHeight, % "ahk_id" gui_id
CoordMode, Mouse, Screen
MouseGetPos, mouseX, mouseY
minWidth := 200
, minHeight := 150
If isResizing {
winSYPos := winY + winHeight
winEXPos := winX + winWidth
If InStr(resizeBorder, "W") {
newWidth := winEXPos - mouseX
If (newWidth > minWidth && mouseX > 0)
SetWindowPosition(gui_id,mouseX,,newWidth)
} Else If InStr(resizeBorder, "E") {
newWidth := mouseX - winX
If (newWidth > minWidth)
SetWindowPosition(gui_id,,,newWidth)
}
If InStr(resizeBorder, "N") {
newHeight := winSYPos - mouseY
If (newHeight > minHeight && mouseY > 0)
SetWindowPosition(gui_id,,mouseY,,newHeight)
} Else If InStr(resizeBorder, "S") {
newHeight := mouseY - winY
If (newHeight > minHeight)
SetWindowPosition(gui_id,,,,newHeight)
}
}
}
SetWindowPosition(hwnd, x := "", y := "", w := "", h := "") {
WinGetPos, winX, winY, winW, winH, % "ahk_id" hwnd
x := x ? x : winX ; Set vars to found positions if params are blank
, y := y ? y : winY
, w := w ? w : winW
, h := h ? h : winH
DllCall("SetWindowPos","uint",hwnd,"uint",0
,"int",x,"int",y,"int",w,"int",h
,"uint",0x40)
ToolTip, % "x" x " y" y " w" w " h" h
}