The code below employs a method, which is likely the most efficient to create a mobile frame. It simply draws a rectangle and avoids the overhead of drawing a solid rectangle then removing some area inside.
For documentation on the various calls, refer to the
MSDN Library.
Code:
OnExit, handle_exit
update_period = 100
toggle_period := 4*update_period
toggle_time := toggle_period
frame_c = 0
frame_c[0] = 0x808000
frame_c[1] := frame_c[0]^0xFFFFFF
frame_w = 100 ; width
frame_h = 100 ; height
frame_t = 5 ; thickness
; frame
Gui, +AlwaysOnTop -Caption
Gui, Color, Black
Gui, Show, w%a_ScreenWidth% h%a_ScreenHeight% x0 y0, Frame Test
WinGet, hw_frame, id, Frame Test
WinSet, Transcolor, Black, ahk_id %hw_frame%
hdc_frame := GetDC( hw_frame )
; buffer
hdc_buffer := CreateCompatibleDC( hdc_frame )
hbm_buffer := CreateCompatibleBitmap( hdc_frame, a_ScreenWidth, a_ScreenHeight )
SelectObject( hdc_buffer, hbm_buffer )
h_region := CreateRectRgn( 0, 0, 0, 0 )
SetTimer, timer_MoveFrame, %update_period%
return
handle_exit:
DrawFrame( 0, 0, 0, 0, 0, 0, true )
DeleteObject( h_region )
DeleteObject( hbm_buffer )
DeleteDC( hdc_frame )
DeleteDC( hdc_buffer )
ExitApp
timer_MoveFrame:
SetBatchLines, -1
CoordMode, mouse, screen
MouseGetPos, cx, cy
toggle_time -= update_period
if ( toggle_time = 0 )
{
frame_c := !frame_c
toggle_time := toggle_period
}
DrawFrame( cx-frame_w//2, cy-frame_h//2, frame_w, frame_h, frame_t, frame_c[%frame_c%] )
return
DrawFrame( p_x, p_y, p_w, p_h, p_t, p_c, p_restore=false )
{
global hdc_frame, hdc_buffer, h_region
static buffer_state, old_x, old_y, old_w, old_h
SRCCOPY = 0x00CC0020
if ( p_x < 0 )
p_x = 0
if ( p_y < 0 )
p_y = 0
t_x := a_ScreenWidth-p_w
if ( p_x > t_x )
p_x := t_x
t_y := a_ScreenHeight-p_h
if ( p_y > t_y )
p_y := t_y
if ( buffer_state = "full" )
{
DllCall( "gdi32.dll\BitBlt", "uint", hdc_frame, "int", old_x, "int", old_y, "int", old_w, "int", old_h, "uint", hdc_buffer, "int", 0, "int", 0, "uint", SRCCOPY )
if ( p_restore )
return
}
else
buffer_state = full
old_x := p_x
old_y := p_y
old_w := p_w
old_h := p_h
DllCall( "gdi32.dll\BitBlt", "uint", hdc_buffer, "int", 0, "int", 0, "int", p_w, "int", p_h, "uint", hdc_frame, "int", p_x, "int", p_y, "uint", SRCCOPY )
DllCall( "gdi32.dll\SetRectRgn", "uint", h_region, "int", p_x, "int", p_y, "int", p_x+p_w, "int", p_y+p_h )
h_brush := DllCall( "gdi32.dll\CreateSolidBrush", "uint", p_c )
DllCall( "gdi32.dll\FrameRgn", "uint", hdc_frame, "uint", h_region, "uint", h_brush, "int", p_t, "int", p_t )
DeleteObject( h_brush )
}
CreateCompatibleDC( p_dc )
{
return, DllCall( "gdi32.dll\CreateCompatibleDC", "uint", p_dc )
}
DeleteDC( p_dc )
{
DllCall( "gdi32.dll\DeleteDC", "uint", p_dc )
}
GetDC( p_hw )
{
return, DllCall( "GetDC", "uint", p_hw )
}
DeleteObject( p_object )
{
DllCall( "gdi32.dll\DeleteObject", "uint", p_object )
}
SelectObject( p_dc, p_bitmap )
{
DllCall( "gdi32.dll\SelectObject", "uint", p_dc, "uint", p_bitmap )
}
CreateCompatibleBitmap( p_dc, p_w, p_h )
{
return, DllCall( "gdi32.dll\CreateCompatibleBitmap", "uint", p_dc, "int", p_w, "int", p_h )
}
CreateRectRgn( p_x1, p_y1, p_x2, p_y2 )
{
return, DllCall( "gdi32.dll\CreateRectRgn", "int", p_x1, "int", p_y1, "int", p_x2, "int", p_y2 )
}