AutoHotkey Community

It is currently May 27th, 2012, 3:33 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 24 posts ]  Go to page Previous  1, 2
Author Message
 Post subject:
PostPosted: June 8th, 2010, 11:40 pm 
Offline

Joined: November 24th, 2008, 7:22 pm
Posts: 73
I got hooked on this script and started to noodle with it. Well, I may have gotten carried away. It's still a work in progress. I present it here "as is". I did not change the documentation in the header to match my changes.

Here's what I've done:
- automatically delete the temporary work file
- allow a drawing to be appended after replay when NOT compiled
- changed the playback script to use the drawLine function (this eliminated mouse interference during playback and fixed a problem where the playback would not obey the mouse button UP)
- added a help function to F1 and moved the function of the other keys to F2 thru F5
- added color names (and moved the color order around a bit)
- added a transient tooltip that shows the color and width when changed

Code:
;
;modified by Relayer 06-08-2010

; from:
; http://www.autohotkey.com/forum/viewtopic.php?p=253705#253705
; Shimanov, Metaxal, maximo3491
; If Shimanov agrees:
; GNU General Public License 3.0 or higher <http://www.gnu.org/licenses/gpl-3.0.txt>

; Version 1.6 - Metaxal 2010/06/06
;   - creates the batch scripts (DrawOnSCreen and compile) to replay files and compile them
;   - script can replay a saved script! (not anymore in paint, but on the screen directly!)
;     using the batch file.
;     Works even with multiple-screens!
;   - keypresses are also logged! (erase screen, widen pen, etc.)
; Version 1.5 - Metaxal 2010/06/05
;   - added multiple display support

; TODO:
; - more colors, better UI ?
; - scale mouse move to screen resolution ? (-> still ok if script replayed on a different screen)
;   not easy to do
; - command line parameters (initial width, color, etc.)


/*
    ********************
    *** README FIRST ***
    ********************

   
    ** Simple usage **

Just launch this script, draw on the screen with mouse moves and key F1-F4,
and press Escape when you're finished.

F1: change color
F2: erase screen
F3: pen_width-
F4: pen_width+


Notice that 4 files are created the first time you launch DrawOnScreen.ahk:
- DrawOnScreen.bat (see next section)
- compile.bat (to create executables)
- painting.ahk (the saved mouse movements)
- paintingtemp.ahk (temporary work file)

WARNING: From now on, you should must DrawOnScreen.bat instead of DrawOnScreen.ahk

    ** Replaying mouse-move scripts **

After pressing Escape, the mouse movements are saved to "painting.ahk".
Rename this file to whatever name you want to save it.

To replay a saved file, just drag&drop it onto the batch script "DrawOnScreen.bat".
At the end of the replay, you may need to press Escape to return to Windows.

    ** Compiling move scripts **

To create a stand-alone executable from a saved move file,
just drag&drop it onto the batch script "compile.bat".
At the end of the replay, it will automatically exit after 1 second.

You can now send this .exe file to a friend!
Beware however that his/her screen resolution may be different from yours.

    ** Modifying a move script **

To modify the mouse speed, or end the script as soon as it is finished,
check the first and last lines of the generated script.
You can of course make other adjustments if you need.
 
*/

; added by JB
; Menu, Tray, Icon, %A_ScriptDir%\159.ico
TO := 0

create_batch(bat_file, text) {
    if !( A_IsCompiled OR FileExist(bat_file))
        FileAppend %text%, %bat_file%
}

compile_bat =
(
:: move to script directory
cd /d `%0\..

copy `%1 paintingtemp.ahk
>> paintingtemp.ahk echo.
>> paintingtemp.ahk echo Sleep 1000
>> paintingtemp.ahk echo ExitApp
"%A_AhkPath%\..\Compiler\Ahk2exe.exe" /in DrawOnScreen.ahk /out "`%~n1.exe"
)

; Create the compiler if does not exists
create_batch("compile.bat", compile_bat)

drawonscreen_bat =  ; no interpolation of variables
( %
:: move to script directory
cd /d %0\..

:: does nothing if %1 does not exist:
copy %1 paintingtemp.ahk
start c:\utilities\autohotkey\autohotkey.exe DrawOnScreenJB2.ahk %1
)

if !( A_IsCompiled OR FileExist("DrawOnScreen.bat"))
{
    ; Create batch launching file if does not exist (and not compiled)
    create_batch("DrawOnScreen.bat", drawonscreen_bat)
    MsgBox Please now use the DrawOnScreen.bat file
    ExitApp
}


color_codes=0x000000,0x0000FF,0xFF0000,0x008000,0x00FFFF,0xC0C0C0,0x808080,0xFFFFFF,0x800000,0x800080,0xFF00FF,0x00FF00,0x808000,0xFFFF00,0x000080,0x008080
color_names=Black,Red,Blue,Green,Yellow,Silver,Gray,White,Navy,Purple,Fuchsia,Lime,Teal,Aqua,Maroon,Olive

max_width = 200 ; max width of the brush

log_movement := !( A_IsCompiled ) && !(%0% > 0)  ; 0 for false, 1 for true
append_movement := false
;msgbox, %log_movement%
CoordMode, Mouse, Screen

Process, Exist
pid_this := ErrorLevel

hdc_screen := DllCall( "GetDC", "uint", 0 )

; Get the number of monitors:
SysGet, MonitorCount, MonitorCount

MonitorNum := 1 ; primary monitor

; if multiple displays:
if (MonitorCount > 1) {
    Gui, Add, Text,, Select the display:
    Gui, Add, Text,, 1
    Gui, Add, UpDown, vMonitorNum Range1-%MonitorCount%, 1
    Gui, Add, Button, default, OK  ; The label ButtonOK (if it exists) will be run when the button is pressed.
    Gui, Show
    return  ; End of auto-execute section. The script is idle until the user does something.
}

ButtonOK:
Gui, Submit
Gui, Destroy
Sleep, 100 ; wait for the GUI to hide

; Get info about the monitor size
SysGet, Screen, Monitor, %MonitorNum%
; -> creates the 4 variables ScreenLeft, ScreenTop, ScreenRight, ScreenBottom

ScreenWidth := ScreenRight - ScreenLeft
ScreenHeight := ScreenBottom - ScreenTop


; Create a working buffer
hdc_buffer := DllCall( "CreateCompatibleDC", "uint", hdc_screen )
hbm_buffer := DllCall( "CreateCompatibleBitmap", "uint", hdc_screen, "int", ScreenWidth, "int", ScreenHeight )
DllCall( "SelectObject", "uint", hdc_buffer, "uint", hbm_buffer )

; Init the buffer with a screenshot
DllCall( "BitBlt", "uint", hdc_buffer, "int", 0, "int", 0, "int", ScreenWidth, "int", ScreenHeight, "uint", hdc_screen, "int", ScreenLeft, "int", ScreenTop, "uint", 0x00CC0020 )

; Create a (completely transparent) window with the size of the display
Gui, +AlwaysOnTop -Caption
Gui, Show, x%ScreenLeft% y%ScreenTop% w%ScreenWidth% h%ScreenHeight%

; Get the hwnd associated with the canvas of the current window
WinGet, hw_canvas, ID, ahk_class AutoHotkeyGUI ahk_pid %pid_this%

; Get the canvas of the created window
hdc_canvas := DllCall( "GetDC", "uint", hw_canvas )

; Begin by drawing the background in the canvas
DllCall( "BitBlt", "uint", hdc_canvas, "int", 0, "int", 0, "int", ScreenWidth, "int", ScreenHeight, "uint", hdc_buffer, "int", 0, "int", 0, "uint", 0x00CC0020 )

; not exactly because colors are reverse in SetPixel...
StringSplit colors, color_codes, `,
StringSplit cnames, color_names, `,
color_index := 1  ;first color to show

color := colors%color_index%

width := 2
x_last := 0
y_last := 0
Pace := 0

SetBatchLines, -1
SetMouseDelay 1.5

left_down := false
right_down := false

/*
http://msdn.microsoft.com/en-us/library/ms645616(VS.85).aspx
wParam:
*/
WM_MOUSEMOVE = 0x0200
/*
; numbers
MK_CONTROL  := 0x0008
MK_LBUTTON  := 0x0001
MK_MBUTTON  := 0x0010
MK_RBUTTON  := 0x0002
MK_SHIFT    := 0x0004
MK_XBUTTON1 := 0x0020
MK_XBUTTON2 := 0x0040
*/


if log_movement
{
    log .= "`n`;change the PaceFactor to speed up or slow down the replay"
   log .= "`n`;PaceFactor = 0 is the fastest"
   log .= "`nPaceFactor := 1"
}

#Include *i paintingtemp.ahk

;this has been moved below the include to prevent mouse movements from messing with a replay
;it is enabled after so that an append can take place
if !( A_IsCompiled )
   OnMessage( WM_MOUSEMOVE, "HandleMessage" )


;; End of auto-executed section
return

HandleMessage( p_w, p_l )
{
   global hdc_canvas, hdc_buffer, x_last, y_last, width, color, left_down, right_down, log, log_movement, ScreenLeft, ScreenTop, Pace, append_movement

   x := (p_l & 0xFFFF)
   y := (p_l >> 16)

   lbutton := p_w & 0x0001 ; MK_LBUTTON
   rbutton := p_w & 0x0002 ; MK_RBUTTON

   if (lbutton)
   {
      if not left_down
      {
         SetTimer, Pacer, 10
         left_down := true
         if !(log_movement)
            append_movement := true
      }
      else
      {
         drawLine(x_last, y_last, x, y, color, width)
         log .= "`nSleep, % " . Pace*10 . "*PaceFactor"
         log .= "`ndrawLine(" . x_last . "," . y_last . "," . x . "," . y . "," . color . "," . width . ")"
         Pace := 1
      }
   }
   else if (left_down)
      left_down := false

   if (rbutton)
   {
      if not right_down
      {
         SetTimer, Pacer, 10
         right_down := true
         if !(log_movement)
            append_movement := true
      }
      else
      {
         drawLine(x_last, y_last, x, y, "ERASE", width)
         log .= "`nSleep, % " . Pace*10 . "*PaceFactor"
         log .= "`ndrawLine(" . x_last . "," . y_last . "," . x . "," . y . ",""ERASE"" ," . width . ")"
         Pace := 1
      }
   }
   else if (right_down)
      right_down := false
   
   x_last := x
   y_last := y
}


drawLine(x0, y0, x1, y1, color_ini=0, width=1)
{
   dx := x1 - x0
   dy := y1 - y0
   
   dxy := (Abs(dx) > Abs(dy) ? Abs(dx) : Abs(dy) )
   
   dx := dx / dxy
   dy := dy / dxy
   
   Loop %dxy%
   {
      x0 += dx
      y0 += dy
   
     drawCircle(Round(x0),round(y0), color_ini)
   }
}

drawCircle(x,y, color_ini) {
    global hdc_buffer, hdc_canvas, width, ScreenLeft, ScreenTop, ScreenWidth, ScreenHeight

    cRegion := DllCall( "gdi32.dll\CreateRoundRectRgn", "int", x-width , "int", y-width , "int", x+width , "int", y+width, "int", width*2, "int", width*2 )
    cBrush := DllCall("gdi32.dll\CreateSolidBrush", "uint", color_ini )


    if color_ini=ERASE
    {
        ; from http://msdn.microsoft.com/en-us/library/dd183437%28VS.85%29.aspx
        ; Select clipping region
        DllCall( "SelectClipRgn", "uint", hdc_canvas, "uint", cRegion )
     
        ; Transfer (draw) the bitmap into the clipped rectangle.
        DllCall( "BitBlt", "uint", hdc_canvas, "int", 0, "int", 0, "int", ScreenWidth, "int", ScreenHeight, "uint", hdc_buffer, "int", 0, "int", 0, "uint", 0x00CC0020 )
       
        ; Select the full region back
        DllCall( "SelectClipRgn", "uint", hdc_canvas, "uint", 0 )
    }
    else
        DllCall( "gdi32.dll\FillRgn" , "uint", hdc_canvas , "uint", cRegion , "uint", cBrush )

    DllCall("gdi32.dll\DeleteObject", "uint", cRegion)
    DllCall("gdi32.dll\DeleteObject", "uint", cBrush)
}

rotate_color() {
    global
   color_index++
   if(color_index > 16)
     color_index := 1
   Gosub, ShowTip
}

erase_canvas() {
   global
   DllCall( "BitBlt", "uint", hdc_canvas, "int", 0, "int", 0, "int", ScreenWidth, "int", ScreenHeight, "uint", hdc_buffer, "int", 0, "int", 0, "uint", 0x00CC0020 )
}

width_minus() {
    global
   if width > 1
      width--
   Gosub, ShowTip
}

width_plus() {
    global
   if width < %max_width%
     width++
   Gosub, ShowTip
}

log_function(fun_str) {
    global log
    log .= "`nSleep 10`n" . fun_str
}

F1::
if (TO = 1)
   Goto, nTO
TO := 1
OnMessage( WM_MOUSEMOVE, "" )
   Help = Draw on Screen
   Help = %Help%`n   left = draw
   Help = %Help%`n   right = erase
   Help = %Help%`n   Escape = quit
   Help = %Help%`n   F2 = toggle colors
   Help = %Help%`n   F3/F4 = dec/inc width
   Help = %Help%`n   F5 = erases screen
   ;Help = %Help%`n   F1: toggle colors
ToolTip, %Help%
Return
nTO:
TO := 0
Tooltip
if !( A_IsCompiled )
   OnMessage( WM_MOUSEMOVE, "HandleMessage" )
Return


ShowTip:
if !( A_IsCompiled )
{
   color := colors%color_index%
   cname := cnames%color_index%
   Tip := cnames%color_index%
   ToolTip, %Tip% %width%
   SetTimer, EndTip, 700
}   
Return   
EndTip:
   SetTimer, EndTip, Off
   ToolTip
Return
 

F2::
    rotate_color()
    log_function("rotate_color()")
return
   

F5::
    erase_canvas()
    log_function("erase_canvas()")
return

F3::
    width_minus()
    log_function("width_minus()")
return

F4::
    width_plus()
    log_function("width_plus()")
return


Pacer:
   Pace += 1
Return



Escape::
if ((log_movement || append_movement) && (Pace <> 0))
{
   if !(append_movement)
      FileDelete, painting.ahk
   log .= "`n`;Sleep 1000 `; uncomment these two lines..."
   log .= "`n`;ExitApp `; ...to end the script as soon as it is finished"
   FileAppend, %log%, painting.ahk
}
FileDelete, paintingtemp.ahk
ExitApp


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 9th, 2010, 11:12 am 
Offline

Joined: March 4th, 2009, 3:27 pm
Posts: 25
Nice! Good work!

I've updated the script with your modifications.

Also changed:
- fixed: generated scripts now depend on the name of the main ahk file.
- restored red as first color (sorry ;) )
- put the main parameters at the top of the script, so that they can be easily changed
- changed extension of generated files (these are not plain standalone AHK scripts)
- updated docs

The only thing I regret is that now we don't have as fine a control on the speed of mouse moves as before, e.g. for fast but not light speed movements.


Last edited by Metaxal on June 9th, 2010, 9:15 pm, edited 2 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 9th, 2010, 9:08 pm 
Offline

Joined: November 24th, 2008, 7:22 pm
Posts: 73
I like your refinements. Let's keep enhancing this thing.

Quote:
- restored red as first color (sorry Wink )

Oh..... alright :)

Quote:
- put the main parameters at the top of the script, so that they can be easily changed

Good move!

Quote:
- changed extension of generated files (these are not plain standalone AHK scripts)

YES! this was bugging me but it didn't dawn on me to change the extension. Good work.

Quote:
The only thing I regret...

Yes, I struggled with this too but felt the benefits outweighed the downside. It looked like the limiting factor was the insertion of a Sleep command. It posed a delay of non-zero even if it is set small. There might be a way to comment out all the Sleep statements if desired. I like that you clamped the Sleep value to 1000. Longer delays would baffle anyone watching a playback.

Relayer


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 9th, 2010, 9:18 pm 
Offline

Joined: March 4th, 2009, 3:27 pm
Posts: 25
New version again:
- added NumpadAdd/PgUp and NumpadSub/PgDown to control replay speed
- moved tooltips to top left, because it messes with drawing ;
retored drawing while help is on.

Relayer wrote:
Yes, I struggled with this too but felt the benefits outweighed the downside.


Absolutely.
In fact, it even solves a problem I had with mouse delays on another computer.

Anyway now it should be better with the new parameters, hopefully.

EDIT:
New version again:
- fixed: bugs with show/hide tooltips
- shows mouse pointer with width and color
- erase the background with current color (F6)
- uses Mbutton, MouseWheel

Now uses an intermediate buffer, which eliminates also the bug when drawing over the tooltip.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 19th, 2010, 2:47 pm 
Offline
User avatar

Joined: September 8th, 2008, 12:26 am
Posts: 1048
Location: Ploieşti, RO
• Running the batch files I got an error "Invalid switch: /D" under Win98SE. Dunno what that switch is supposed to do.
• To get the batch files to autoclose when finished under Win9x, they must end with the following commands and a new line <CR>:
@CLS
@EXIT

• playing a recorded painting.ahkinc by dropping it on DrawOnScreen.bat works, but running the same script, compiled, doesn't.

Glitches apart, the script comes out nicely. There's room for improvement so I'll be watching the development whenever possible. Thanks and keep it up! ;)

P.S. A tooltip to signal "Playback finished" would be useful, when auto exit is not active.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 4th, 2010, 10:27 am 
Offline
User avatar

Joined: May 18th, 2010, 3:10 pm
Posts: 1179
Location: Sweden
Hey and thanks for the neato script! I can't seem to get it to work for my purpose though, since I want to use it to notate things in a fullscreen program (Starcraft II).

I found a good workaround (to make SCII run in Windowed mode, but in full size), but if you are looking for ways to improve your script, it would be nice if it didn't deactivate windows. The optimal would of course be if the .bat could run "hidden" in the background, not making its' command window foremost at any time.

Didn't manage to solve it myself though, despite trying a couple of things.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 5th, 2010, 6:29 pm 
Offline

Joined: March 4th, 2009, 3:27 pm
Posts: 25
Not much time for this right now, but you could try to make an AHK script launcher instead of a .bat script.
There are options to run it hidden.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 25th, 2010, 12:33 pm 
Offline

Joined: July 25th, 2010, 12:28 pm
Posts: 5
Is there any way to save the painting in jpg or bmp format?


Report this post
Top
 Profile  
Reply with quote  
PostPosted: July 27th, 2010, 2:31 pm 
Hi!

I often have to use a screenshot capture tool for my work and I could completely replace it with this script if I could draw simple rectangles and arrows.

Is this something that would be easy to implement?

Thanks!


Report this post
Top
  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 24 posts ]  Go to page Previous  1, 2

All times are UTC [ DST ]


Who is online

Users browsing this forum: xXDarknessXx and 14 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group