Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Impossible to Save a WebCam Shot into an image file?


  • Please log in to reply
18 replies to this topic
goldensoft
  • Members
  • 11 posts
  • Last active: Oct 17 2007 07:04 PM
  • Joined: 23 Jul 2007
For the past 3 days I'm trying to save a webcam shot to an image file but until now no luck. Bellow is the script that I'm using. This script was originally created by daonlyfreez <!-- m -->http://www.autohotke...topic17042.html<!-- m --> it allows to copy the current webcam image to the clipboard but lacks the ability to save the image to a file. Any ideas on how to resolve this?

; http://ej.bantz.com/video/
; http://ej.bantz.com/video/detail/

; http://www.dotnet4all.com/dotnet-code/2004/12/video-capture.html

/*
Full blown app possible settings/options (inspired by Dorgem)

* Video stream:

resolution
pixel depth and compression
size (bytes)

* Capture:

1 - file

filetype (avi/pictures)
compression
framerate
location/path
watermark
auto-name
refreshrate (replace or add to max)

2 - ftp (file settings +)

url:port
log

* Motion detection:

sensitivity
action (run, email)

* Multiple camera support ???

*/

; Basic Demo - v 0.2

hModule := DllCall("LoadLibrary", "str", "avicap32.dll")

Gui, Add, GroupBox, x4 y4 w492 h100, Available Video Drivers
Gui, Add, ListView, x8 y20 w400 h80 vCapDriversLV, Index|Name
Gui, Add, Picture, x434 y16 w32 h32 Icon204, %A_WinDir%\system32\shell32.dll
Gui, Add, Button, x412 y50 w80 h24 gRefreshDrivers, Refresh
Gui, Add, Button, x412 y76 w80 h24 gSelectDriver vSelectDriverB, Select


; --- Video preview section of Gui
Gui, Add, GroupBox, x4 y108 w492 h262, Video

; Video preview placeholder
Gui, Add, Text, x10 y124 w320 h240 vVidPlaceholder
GuiControl, +0x7, VidPlaceholder ; frame
Gui, Font, s32
Gui, Add, Text, x32 y200 w280 h64 Center, Preview
Gui, Font

Gui, Add, CheckBox, x340 y120 w100 h24 vPreviewToggleState gPreviewToggle, Preview video
Gui, Add, Button, x440 y120 w50 h24 gCopyToClipBoard, Copy
Gui, Add, Button, x400 y160 w90 h24 gSenToFile, &Send to File

/*
; --- Presets section
Gui, Add, GroupBox, x336 y144 w154 h220, Presets

Gui, Add, DropDownList, x342 y164 w142 h30 r30 vPresetChoice, Create new preset...||My save to picture set|My save to avi set|My save to ftp|My motion detection set

Gui, Add, Button, x342 y190 w70 h24 vSelectPresetB, Select
Gui, Add, Button, x414 y190 w70 h24 vNewPresetB, Edit

Gui, Add, Text, x342 y220 w142 h106 vPresetInfoT,

Gui, Add, Button, x342 y334 w70 h24 vRunPresetB, Run
Gui, Add, Button, x414 y334 w70 h24 vStopPresetB, Stop

*/

; --- Statusbar
Gui, Add, StatusBar,, Done
SB_SetIcon("shell32.dll", 222, 1)

; Get drivers
GoSub, RefreshDrivers

; Get handle of Gui
Gui +LastFound
hwndParent := WinExist()

; Show
Gui, Show, x770 y200 w500 h400, Video For Windows for AutoHotkey - VFW4AHK

;Gosub, ConnectToDriver

Return

PreviewToggle:
msgbox Only once!
;  If PreviewToggleState
    GoSub ConnectToDriver
;  Else
;    GoSub DisconnectDriver
Return


ConnectToDriver:
  ; --- Connect and preview
  capHwnd := Cap_CreateCaptureWindow(hwndParent, 10, 124, 320, 240)
  ;ToolTip % errorlevel
 
  WM_CAP := 0x400
  WM_CAP_DRIVER_CONNECT := WM_CAP + 10
  WM_CAP_DRIVER_DISCONNECT := WM_CAP + 11
  WM_CAP_EDIT_COPY := WM_CAP + 30
  WM_CAP_SET_PREVIEW := WM_CAP + 50
  WM_CAP_SET_PREVIEWRATE := WM_CAP + 52
  WM_CAP_SET_SCALE := WM_CAP + 53
 
  ; Connect to driver
  if SelectedDriver =
  {
    MsgBox, 16, Error!, You didn't select a video driver
    Return
  }
  SendMessage, WM_CAP_DRIVER_CONNECT, %SelectedDriver%, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ; Set the preview scale
  SendMessage, WM_CAP_SET_SCALE, 1, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ; Set the preview rate in milliseconds
  SendMessage, WM_CAP_SET_PREVIEWRATE, 66, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ; Start previewing the image from the camera
  SendMessage, WM_CAP_SET_PREVIEW, 1, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ToolTip
Return



CopyToClipBoard:
  SendMessage, WM_CAP_EDIT_COPY, 0, 0, , ahk_id %capHwnd%
Return

SenToFile:
    imagefile = C:\image.bmp
    SendMessage, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0, , ahk_id %capHwnd%
    SendMessage WM_CAP_FILE_SAVEDIB, 0,0, %imagefile%, ahk_id%capHwnd%
    ;DllCall("User32\SendMessage", Uint, ahk_id%capHwnd%, Uint, %WM_CAP_FILE_SAVEDIB%, Uint, 0, Str, %imagefile%)   
    ToolTip % errorlevel 
return


DisconnectDriver:
  SendMessage, WM_CAP_DRIVER_DISCONNECT, 1, 0, , ahk_id %capHwnd%
Return


RefreshDrivers:
  foundDriver = 0
  LV_Delete()
  Loop
  {
    thisInfo := Cap_GetDriverDescription(A_Index-1)
    If thisInfo
    {
      foundDriver = 1
      LV_Add("", A_Index-1, thisInfo)
    }
    Else
      Break
  }
  If !foundDriver
  {
    LV_Delete()
    LV_Add("", "", "Could not get video drivers")
    GuiControl, Disable, CapDriversLV
    GuiControl, Disable, SelectDriverB
  }
Return
 
 
SelectDriver:
  FocusedRowNumber := LV_GetNext(0, "F")  ; Find the focused row.
  if not FocusedRowNumber  ; No row is focused.
    return
  LV_GetText(SelectedDriver, FocusedRowNumber, 1)
Return







/*
'// The two functions exported by AVICap
Declare Function capCreateCaptureWindowA Lib "avicap32.dll" ( _
    ByVal lpszWindowName As String, _
    ByVal dwStyle As Long, _
    ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Integer, _
    ByVal hWndParent As Long, ByVal nID As Long) As Long
   
Declare Function capGetDriverDescriptionA Lib "avicap32.dll" ( _
    ByVal wDriver As Integer, _
    ByVal lpszName As String, _
    ByVal cbName As Long, _
    ByVal lpszVer As String, _
    ByVal cbVer As Long) As Boolean
*/

Cap_CreateCaptureWindow(hWndParent, x, y, w, h)
{
  WS_CHILD := 0x40000000
  WS_VISIBLE := 0x10000000
 
  lpszWindowName := "test"
 
  lwndC := DLLCall("avicap32.dll\capCreateCaptureWindowA"
                  , "Str", lpszWindowName
                  , "UInt", WS_VISIBLE | WS_CHILD ; dwStyle
                  , "Int", x
                  , "Int", y
                  , "Int", w
                  , "Int", h
                  , "UInt", hWndParent
                  , "Int", 0)
 
  ;msgbox % lwndC " | " errorlevel " | " lpszWindowName " | " hwndParent
  Return lwndC
}

Cap_GetDriverDescription(wDriver)
{
  VarSetCapacity(lpszName, 100)
  VarSetCapacity(lpszVer, 100)
  res := DLLCall("avicap32.dll\capGetDriverDescriptionA"
                  , "Short", wDriver
                  , "Str", lpszName
                  , "Int", 100
                  , "Str", lpszVer
                  , "Int", 100)
  If res
    capInfo := lpszName ; " | " lpszVer
  Return capInfo
}

GuiClose:
  GoSub, DisconnectDriver
  DllCall("FreeLibrary", "str", hModule)
  ExitApp
Return

!r::Reload ; for debugging

The section of the code responsible for handling the image file generation is:
SenToFile:
    imagefile = C:\image.bmp
    SendMessage, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0, , ahk_id %capHwnd%
    SendMessage WM_CAP_FILE_SAVEDIB, 0,0, %imagefile%, ahk_id %capHwnd%
    ;DllCall("User32\SendMessage", Uint, ahk_id %capHwnd%, Uint, %WM_CAP_FILE_SAVEDIB%, Uint, 0, Str, %imagefile%)   
    ToolTip % errorlevel 
return


daonlyfreez
  • Members
  • 995 posts
  • Last active: Jan 23 2013 08:16 AM
  • Joined: 16 Mar 2005
I cannot test right now, but you'll need the constants

WM_USER = 0x0400
WM_CAP_START = WM_USER
WM_CAP_GRAB_FRAME_NOSTOP := WM_USER + 61
WM_CAP_FILE_SAVEDIB := WM_CAP_START + 25

Posted Image mirror 1mirror 2mirror 3ahk4.me • PM or Posted Image

goldensoft
  • Members
  • 11 posts
  • Last active: Oct 17 2007 07:04 PM
  • Joined: 23 Jul 2007
Thanks daonlyfreez you are correct its needed to add these constants the script is now:

; http://ej.bantz.com/video/
; http://ej.bantz.com/video/detail/

; http://www.dotnet4all.com/dotnet-code/2004/12/video-capture.html

/*
Full blown app possible settings/options (inspired by Dorgem)

* Video stream:

resolution
pixel depth and compression
size (bytes)

* Capture:

1 - file

filetype (avi/pictures)
compression
framerate
location/path
watermark
auto-name
refreshrate (replace or add to max)

2 - ftp (file settings +)

url:port
log

* Motion detection:

sensitivity
action (run, email)

* Multiple camera support ???

*/

; Basic Demo - v 0.2

hModule := DllCall("LoadLibrary", "str", "avicap32.dll")

Gui, Add, GroupBox, x4 y4 w492 h100, Available Video Drivers
Gui, Add, ListView, x8 y20 w400 h80 vCapDriversLV, Index|Name
Gui, Add, Picture, x434 y16 w32 h32 Icon204, %A_WinDir%\system32\shell32.dll
Gui, Add, Button, x412 y50 w80 h24 gRefreshDrivers, Refresh
Gui, Add, Button, x412 y76 w80 h24 gSelectDriver vSelectDriverB, Select


; --- Video preview section of Gui
Gui, Add, GroupBox, x4 y108 w492 h262, Video

; Video preview placeholder
Gui, Add, Text, x10 y124 w320 h240 vVidPlaceholder
GuiControl, +0x7, VidPlaceholder ; frame
Gui, Font, s32
Gui, Add, Text, x32 y200 w280 h64 Center, Preview
Gui, Font

Gui, Add, CheckBox, x340 y120 w100 h24 vPreviewToggleState gPreviewToggle, Preview video
Gui, Add, Button, x440 y120 w50 h24 gCopyToClipBoard, Copy
Gui, Add, Button, x400 y160 w90 h24 gSenToFile, &Send to File

/*
; --- Presets section
Gui, Add, GroupBox, x336 y144 w154 h220, Presets

Gui, Add, DropDownList, x342 y164 w142 h30 r30 vPresetChoice, Create new preset...||My save to picture set|My save to avi set|My save to ftp|My motion detection set

Gui, Add, Button, x342 y190 w70 h24 vSelectPresetB, Select
Gui, Add, Button, x414 y190 w70 h24 vNewPresetB, Edit

Gui, Add, Text, x342 y220 w142 h106 vPresetInfoT,

Gui, Add, Button, x342 y334 w70 h24 vRunPresetB, Run
Gui, Add, Button, x414 y334 w70 h24 vStopPresetB, Stop

*/

; --- Statusbar
Gui, Add, StatusBar,, Done
SB_SetIcon("shell32.dll", 222, 1)

; Get drivers
GoSub, RefreshDrivers

; Get handle of Gui
Gui +LastFound
hwndParent := WinExist()

; Show
Gui, Show, x770 y200 w500 h400, Video For Windows for AutoHotkey - VFW4AHK

;Gosub, ConnectToDriver

Return

PreviewToggle:
msgbox Only once!
;  If PreviewToggleState
    GoSub ConnectToDriver
;  Else
;    GoSub DisconnectDriver
Return


ConnectToDriver:
  ; --- Connect and preview
  capHwnd := Cap_CreateCaptureWindow(hwndParent, 10, 124, 320, 240)
  ;ToolTip % errorlevel
 

  WM_USER = 0x0400
  WM_CAP_START = WM_USER
  WM_CAP_GRAB_FRAME_NOSTOP := WM_USER + 61
  WM_CAP_FILE_SAVEDIB := WM_CAP_START + 25


  WM_CAP := 0x400
  WM_CAP_DRIVER_CONNECT := WM_CAP + 10
  WM_CAP_DRIVER_DISCONNECT := WM_CAP + 11
  WM_CAP_EDIT_COPY := WM_CAP + 30
  WM_CAP_SET_PREVIEW := WM_CAP + 50
  WM_CAP_SET_PREVIEWRATE := WM_CAP + 52
  WM_CAP_SET_SCALE := WM_CAP + 53
 
  ; Connect to driver
  if SelectedDriver =
  {
    MsgBox, 16, Error!, You didn't select a video driver
    Return
  }
  SendMessage, WM_CAP_DRIVER_CONNECT, %SelectedDriver%, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ; Set the preview scale
  SendMessage, WM_CAP_SET_SCALE, 1, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ; Set the preview rate in milliseconds
  SendMessage, WM_CAP_SET_PREVIEWRATE, 66, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ; Start previewing the image from the camera
  SendMessage, WM_CAP_SET_PREVIEW, 1, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ToolTip
Return



CopyToClipBoard:
  SendMessage, WM_CAP_EDIT_COPY, 0, 0, , ahk_id %capHwnd%
Return

SenToFile:
    imagefile = C:\image.bmp
    SendMessage, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0, , ahk_id %capHwnd%
    SendMessage WM_CAP_FILE_SAVEDIB, 0,0, %imagefile%, ahk_id%capHwnd%
    ;DllCall("User32\SendMessage", Uint, ahk_id%capHwnd%, Uint, %WM_CAP_FILE_SAVEDIB%, Uint, 0, Str, %imagefile%)   
    ToolTip % errorlevel
return


DisconnectDriver:
  SendMessage, WM_CAP_DRIVER_DISCONNECT, 1, 0, , ahk_id %capHwnd%
Return


RefreshDrivers:
  foundDriver = 0
  LV_Delete()
  Loop
  {
    thisInfo := Cap_GetDriverDescription(A_Index-1)
    If thisInfo
    {
      foundDriver = 1
      LV_Add("", A_Index-1, thisInfo)
    }
    Else
      Break
  }
  If !foundDriver
  {
    LV_Delete()
    LV_Add("", "", "Could not get video drivers")
    GuiControl, Disable, CapDriversLV
    GuiControl, Disable, SelectDriverB
  }
Return
 
 
SelectDriver:
  FocusedRowNumber := LV_GetNext(0, "F")  ; Find the focused row.
  if not FocusedRowNumber  ; No row is focused.
    return
  LV_GetText(SelectedDriver, FocusedRowNumber, 1)
Return







/*
'// The two functions exported by AVICap
Declare Function capCreateCaptureWindowA Lib "avicap32.dll" ( _
    ByVal lpszWindowName As String, _
    ByVal dwStyle As Long, _
    ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Integer, _
    ByVal hWndParent As Long, ByVal nID As Long) As Long
   
Declare Function capGetDriverDescriptionA Lib "avicap32.dll" ( _
    ByVal wDriver As Integer, _
    ByVal lpszName As String, _
    ByVal cbName As Long, _
    ByVal lpszVer As String, _
    ByVal cbVer As Long) As Boolean
*/

Cap_CreateCaptureWindow(hWndParent, x, y, w, h)
{
  WS_CHILD := 0x40000000
  WS_VISIBLE := 0x10000000
 
  lpszWindowName := "test"
 
  lwndC := DLLCall("avicap32.dll\capCreateCaptureWindowA"
                  , "Str", lpszWindowName
                  , "UInt", WS_VISIBLE | WS_CHILD ; dwStyle
                  , "Int", x
                  , "Int", y
                  , "Int", w
                  , "Int", h
                  , "UInt", hWndParent
                  , "Int", 0)
 
  ;msgbox % lwndC " | " errorlevel " | " lpszWindowName " | " hwndParent
  Return lwndC
}

Cap_GetDriverDescription(wDriver)
{
  VarSetCapacity(lpszName, 100)
  VarSetCapacity(lpszVer, 100)
  res := DLLCall("avicap32.dll\capGetDriverDescriptionA"
                  , "Short", wDriver
                  , "Str", lpszName
                  , "Int", 100
                  , "Str", lpszVer
                  , "Int", 100)
  If res
    capInfo := lpszName ; " | " lpszVer
  Return capInfo
}

GuiClose:
  GoSub, DisconnectDriver
  DllCall("FreeLibrary", "str", hModule)
  ExitApp
Return

!r::Reload ; for debugging

but there continues to exist some problems on:
SenToFile:
    imagefile = C:\image.bmp
    SendMessage, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0, , ahk_id %capHwnd%
    SendMessage WM_CAP_FILE_SAVEDIB, 0,0, %imagefile%, ahk_id%capHwnd%
    ;DllCall("User32\SendMessage", Uint, ahk_id%capHwnd%, Uint, %WM_CAP_FILE_SAVEDIB%, Uint, 0, Str, %imagefile%)   
    ToolTip % errorlevel
return


this line of code refuses to run
SendMessage WM_CAP_FILE_SAVEDIB, 0,0, %imagefile%, ahk_id%capHwnd%

I tried to use instead
DllCall("User32\SendMessage", Uint, ahk_id%capHwnd%, Uint, %WM_CAP_FILE_SAVEDIB%, Uint, 0, Str, %imagefile%)   

but I had no luck. Any one can help?

Helpy
  • Guests
  • Last active:
  • Joined: --
I see errors:
SendMessage WM_CAP_FILE_SAVEDIB, 0,0, %imagefile%, ahk_id%capHwnd%
Need a space adter ahk_id
DllCall("User32\SendMessage", Uint, ahk_id%capHwnd%, Uint, %WM_CAP_FILE_SAVEDIB%, Uint, 0, Str, %imagefile%)
In function calls, you rarely give a dereference of the variable, and even less of the ahk_id, so it should be:
DllCall("User32\SendMessage", Uint, capHwnd, Uint, WM_CAP_FILE_SAVEDIB, Uint, 0, Str, imagefile)
but the command should do the work.

goldensoft
  • Members
  • 11 posts
  • Last active: Oct 17 2007 07:04 PM
  • Joined: 23 Jul 2007

I see errors:
SendMessage WM_CAP_FILE_SAVEDIB, 0,0, %imagefile%, ahk_id%capHwnd%
Need a space adter ahk_id
DllCall("User32\SendMessage", Uint, ahk_id%capHwnd%, Uint, %WM_CAP_FILE_SAVEDIB%, Uint, 0, Str, %imagefile%)
In function calls, you rarely give a dereference of the variable, and even less of the ahk_id, so it should be:
DllCall("User32\SendMessage", Uint, capHwnd, Uint, WM_CAP_FILE_SAVEDIB, Uint, 0, Str, imagefile)
but the command should do the work.


I agree with you Helpy about the space after ahk_id and about the DllCall but even after these changes the webcamshot/image file is not saved to the harddisk, here is the full script with the new changes:


; http://ej.bantz.com/video/
; http://ej.bantz.com/video/detail/

; http://www.dotnet4all.com/dotnet-code/2004/12/video-capture.html

/*
Full blown app possible settings/options (inspired by Dorgem)

* Video stream:

resolution
pixel depth and compression
size (bytes)

* Capture:

1 - file

filetype (avi/pictures)
compression
framerate
location/path
watermark
auto-name
refreshrate (replace or add to max)

2 - ftp (file settings +)

url:port
log

* Motion detection:

sensitivity
action (run, email)

* Multiple camera support ???

*/

; Basic Demo - v 0.2

hModule := DllCall("LoadLibrary", "str", "avicap32.dll")

Gui, Add, GroupBox, x4 y4 w492 h100, Available Video Drivers
Gui, Add, ListView, x8 y20 w400 h80 vCapDriversLV, Index|Name
Gui, Add, Picture, x434 y16 w32 h32 Icon204, %A_WinDir%\system32\shell32.dll
Gui, Add, Button, x412 y50 w80 h24 gRefreshDrivers, Refresh
Gui, Add, Button, x412 y76 w80 h24 gSelectDriver vSelectDriverB, Select


; --- Video preview section of Gui
Gui, Add, GroupBox, x4 y108 w492 h262, Video

; Video preview placeholder
Gui, Add, Text, x10 y124 w320 h240 vVidPlaceholder
GuiControl, +0x7, VidPlaceholder ; frame
Gui, Font, s32
Gui, Add, Text, x32 y200 w280 h64 Center, Preview
Gui, Font

Gui, Add, CheckBox, x340 y120 w100 h24 vPreviewToggleState gPreviewToggle, Preview video
Gui, Add, Button, x440 y120 w50 h24 gCopyToClipBoard, Copy
Gui, Add, Button, x400 y160 w90 h24 gSenToFile, &Send to File

/*
; --- Presets section
Gui, Add, GroupBox, x336 y144 w154 h220, Presets

Gui, Add, DropDownList, x342 y164 w142 h30 r30 vPresetChoice, Create new preset...||My save to picture set|My save to avi set|My save to ftp|My motion detection set

Gui, Add, Button, x342 y190 w70 h24 vSelectPresetB, Select
Gui, Add, Button, x414 y190 w70 h24 vNewPresetB, Edit

Gui, Add, Text, x342 y220 w142 h106 vPresetInfoT,

Gui, Add, Button, x342 y334 w70 h24 vRunPresetB, Run
Gui, Add, Button, x414 y334 w70 h24 vStopPresetB, Stop

*/

; --- Statusbar
Gui, Add, StatusBar,, Done
SB_SetIcon("shell32.dll", 222, 1)

; Get drivers
GoSub, RefreshDrivers

; Get handle of Gui
Gui +LastFound
hwndParent := WinExist()

; Show
Gui, Show, x770 y200 w500 h400, Video For Windows for AutoHotkey - VFW4AHK

;Gosub, ConnectToDriver

Return

PreviewToggle:
msgbox Only once!
;  If PreviewToggleState
    GoSub ConnectToDriver
;  Else
;    GoSub DisconnectDriver
Return


ConnectToDriver:
  ; --- Connect and preview
  capHwnd := Cap_CreateCaptureWindow(hwndParent, 10, 124, 320, 240)
  ;ToolTip % errorlevel
 

  WM_USER = 0x0400
  WM_CAP_START = WM_USER
  WM_CAP_GRAB_FRAME_NOSTOP := WM_USER + 61
  WM_CAP_FILE_SAVEDIB := WM_CAP_START + 25


  WM_CAP := 0x400
  WM_CAP_DRIVER_CONNECT := WM_CAP + 10
  WM_CAP_DRIVER_DISCONNECT := WM_CAP + 11
  WM_CAP_EDIT_COPY := WM_CAP + 30
  WM_CAP_SET_PREVIEW := WM_CAP + 50
  WM_CAP_SET_PREVIEWRATE := WM_CAP + 52
  WM_CAP_SET_SCALE := WM_CAP + 53
 
  ; Connect to driver
  if SelectedDriver =
  {
    MsgBox, 16, Error!, You didn't select a video driver
    Return
  }
  SendMessage, WM_CAP_DRIVER_CONNECT, %SelectedDriver%, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ; Set the preview scale
  SendMessage, WM_CAP_SET_SCALE, 1, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ; Set the preview rate in milliseconds
  SendMessage, WM_CAP_SET_PREVIEWRATE, 66, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ; Start previewing the image from the camera
  SendMessage, WM_CAP_SET_PREVIEW, 1, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ToolTip
Return



CopyToClipBoard:
  SendMessage, WM_CAP_EDIT_COPY, 0, 0, , ahk_id %capHwnd%
Return

SenToFile:
    imagefile = C:\image.bmp
    SendMessage, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0, , ahk_id %capHwnd%
    ;SendMessage WM_CAP_FILE_SAVEDIB, 0,0, %imagefile%, ahk_id %capHwnd%
    DllCall("User32\SendMessage", Uint, capHwnd, Uint, WM_CAP_FILE_SAVEDIB, Uint, 0, Str, imagefile) 
    ToolTip % errorlevel
return


DisconnectDriver:
  SendMessage, WM_CAP_DRIVER_DISCONNECT, 1, 0, , ahk_id %capHwnd%
Return


RefreshDrivers:
  foundDriver = 0
  LV_Delete()
  Loop
  {
    thisInfo := Cap_GetDriverDescription(A_Index-1)
    If thisInfo
    {
      foundDriver = 1
      LV_Add("", A_Index-1, thisInfo)
    }
    Else
      Break
  }
  If !foundDriver
  {
    LV_Delete()
    LV_Add("", "", "Could not get video drivers")
    GuiControl, Disable, CapDriversLV
    GuiControl, Disable, SelectDriverB
  }
Return
 
 
SelectDriver:
  FocusedRowNumber := LV_GetNext(0, "F")  ; Find the focused row.
  if not FocusedRowNumber  ; No row is focused.
    return
  LV_GetText(SelectedDriver, FocusedRowNumber, 1)
Return







/*
'// The two functions exported by AVICap
Declare Function capCreateCaptureWindowA Lib "avicap32.dll" ( _
    ByVal lpszWindowName As String, _
    ByVal dwStyle As Long, _
    ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Integer, _
    ByVal hWndParent As Long, ByVal nID As Long) As Long
   
Declare Function capGetDriverDescriptionA Lib "avicap32.dll" ( _
    ByVal wDriver As Integer, _
    ByVal lpszName As String, _
    ByVal cbName As Long, _
    ByVal lpszVer As String, _
    ByVal cbVer As Long) As Boolean
*/

Cap_CreateCaptureWindow(hWndParent, x, y, w, h)
{
  WS_CHILD := 0x40000000
  WS_VISIBLE := 0x10000000
 
  lpszWindowName := "test"
 
  lwndC := DLLCall("avicap32.dll\capCreateCaptureWindowA"
                  , "Str", lpszWindowName
                  , "UInt", WS_VISIBLE | WS_CHILD ; dwStyle
                  , "Int", x
                  , "Int", y
                  , "Int", w
                  , "Int", h
                  , "UInt", hWndParent
                  , "Int", 0)
 
  ;msgbox % lwndC " | " errorlevel " | " lpszWindowName " | " hwndParent
  Return lwndC
}

Cap_GetDriverDescription(wDriver)
{
  VarSetCapacity(lpszName, 100)
  VarSetCapacity(lpszVer, 100)
  res := DLLCall("avicap32.dll\capGetDriverDescriptionA"
                  , "Short", wDriver
                  , "Str", lpszName
                  , "Int", 100
                  , "Str", lpszVer
                  , "Int", 100)
  If res
    capInfo := lpszName ; " | " lpszVer
  Return capInfo
}

GuiClose:
  GoSub, DisconnectDriver
  DllCall("FreeLibrary", "str", hModule)
  ExitApp
Return

!r::Reload ; for debugging



and here is the problematic source code:

SenToFile:
    imagefile = C:\image.bmp
    SendMessage, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0, , ahk_id %capHwnd%
    ;SendMessage WM_CAP_FILE_SAVEDIB, 0,0, %imagefile%, ahk_id %capHwnd%
    DllCall("User32\SendMessage", Uint, capHwnd, Uint, WM_CAP_FILE_SAVEDIB, Uint, 0, Str, imagefile) 
    ToolTip % errorlevel
return

Any one knows if its necessary to add something more like WM_CAP_DRIVER_GET_CAPS?

daonlyfreez
  • Members
  • 995 posts
  • Last active: Jan 23 2013 08:16 AM
  • Joined: 16 Mar 2005
WM_USER [color=red]:[/color]= 0x0400
  WM_CAP_START [color=red]:[/color]= WM_USER

Try adding the colons (my bad).
Posted Image mirror 1mirror 2mirror 3ahk4.me • PM or Posted Image

goldensoft
  • Members
  • 11 posts
  • Last active: Oct 17 2007 07:04 PM
  • Joined: 23 Jul 2007

Code (Copy):
WM_USER := 0x0400
WM_CAP_START := WM_USER


Try adding the colons (my bad).


Thanks daonlyfreez :) but I'm afraid this is already in the script. Honestly I don't know what should be changed to save a webcam shot to a file.

I completely searched the Internet and I think this type of functionality hasn't yet been developed for AutoHotKey

System Monitor
  • Members
  • 508 posts
  • Last active: Mar 26 2012 05:13 AM
  • Joined: 09 Mar 2007
Windows Media Encoder and you can use Windows Movie Maker to take a picture from the video

Micahs
  • Members
  • 463 posts
  • Last active: Mar 01 2013 06:01 AM
  • Joined: 01 Dec 2006
https://ahknet.autoh.../test/image.bmp - (Is there something wrong with images? This isn't working!)
First all all, you had a few problems:
WM_CAP_START = WM_USER
Should be:
WM_CAP_START [color=red]:[/color]= WM_USER
You were missing the colon!

Also,
SenToFile:
    imagefile = C:\image.bmp
    SendMessage, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0, , ahk_id %capHwnd%
    ;SendMessage WM_CAP_FILE_SAVEDIB, 0,0, %imagefile%, ahk_id %capHwnd%
    DllCall("User32\SendMessage", Uint, capHwnd, Uint, WM_CAP_FILE_SAVEDIB, Uint, 0, Str, imagefile)
    ToolTip % errorlevel
return
Should be:
SenToFile:
    imagefile = C:\image.bmp
    SendMessage, WM_CAP_FILE_SAVEDIB, 0, &imagefile, , ahk_id %capHwnd%
    ToolTip % errorlevel
return
Your sendmessage was malformed. And you didn't need "WM_CAP_GRAB_FRAME_NOSTOP" because "WM_CAP_FILE_SAVEDIB" already saves the current frame.

Here is a working version:
; http://ej.bantz.com/video/
; http://ej.bantz.com/video/detail/

; http://www.dotnet4all.com/dotnet-code/2004/12/video-capture.html

/*
Full blown app possible settings/options (inspired by Dorgem)

* Video stream:

resolution
pixel depth and compression
size (bytes)

* Capture:

1 - file

filetype (avi/pictures)
compression
framerate
location/path
watermark
auto-name
refreshrate (replace or add to max)

2 - ftp (file settings +)

url:port
log

* Motion detection:

sensitivity
action (run, email)

* Multiple camera support ???

*/

; Basic Demo - v 0.2

hModule := DllCall("LoadLibrary", "str", "avicap32.dll")

Gui, Add, GroupBox, x4 y4 w492 h100, Available Video Drivers
Gui, Add, ListView, x8 y20 w400 h80 vCapDriversLV, Index|Name
Gui, Add, Picture, x434 y16 w32 h32 Icon204, %A_WinDir%\system32\shell32.dll
Gui, Add, Button, x412 y50 w80 h24 gRefreshDrivers, Refresh
Gui, Add, Button, x412 y76 w80 h24 gSelectDriver vSelectDriverB, Select


; --- Video preview section of Gui
Gui, Add, GroupBox, x4 y108 w492 h262, Video

; Video preview placeholder
Gui, Add, Text, x10 y124 w320 h240 vVidPlaceholder
GuiControl, +0x7, VidPlaceholder ; frame
Gui, Font, s32
Gui, Add, Text, x32 y200 w280 h64 Center, Preview
Gui, Font

Gui, Add, CheckBox, x340 y120 w100 h24 vPreviewToggleState gPreviewToggle, Preview video
Gui, Add, Button, x440 y120 w50 h24 gCopyToClipBoard, Copy
Gui, Add, Button, x400 y160 w90 h24 gSenToFile, &Send to File

/*
; --- Presets section
Gui, Add, GroupBox, x336 y144 w154 h220, Presets

Gui, Add, DropDownList, x342 y164 w142 h30 r30 vPresetChoice, Create new preset...||My save to picture set|My save to avi set|My save to ftp|My motion detection set

Gui, Add, Button, x342 y190 w70 h24 vSelectPresetB, Select
Gui, Add, Button, x414 y190 w70 h24 vNewPresetB, Edit

Gui, Add, Text, x342 y220 w142 h106 vPresetInfoT,

Gui, Add, Button, x342 y334 w70 h24 vRunPresetB, Run
Gui, Add, Button, x414 y334 w70 h24 vStopPresetB, Stop

*/

; --- Statusbar
Gui, Add, StatusBar,, Done
SB_SetIcon("shell32.dll", 222, 1)

; Get drivers
GoSub, RefreshDrivers

; Get handle of Gui
Gui +LastFound
hwndParent := WinExist()

; Show
Gui, Show, w500 h400, Video For Windows for AutoHotkey - VFW4AHK

;Gosub, ConnectToDriver

Return

PreviewToggle:
msgbox Only once!
;  If PreviewToggleState
    GoSub ConnectToDriver
;  Else
;    GoSub DisconnectDriver
Return


ConnectToDriver:
  ; --- Connect and preview
  capHwnd := Cap_CreateCaptureWindow(hwndParent, 10, 124, 320, 240)
  ;ToolTip % errorlevel
 

  WM_USER = 0x0400
  WM_CAP_START := WM_USER
  WM_CAP_GRAB_FRAME_NOSTOP := WM_USER + 61
  WM_CAP_FILE_SAVEDIB := WM_CAP_START + 25


  WM_CAP := 0x400
  WM_CAP_DRIVER_CONNECT := WM_CAP + 10
  WM_CAP_DRIVER_DISCONNECT := WM_CAP + 11
  WM_CAP_EDIT_COPY := WM_CAP + 30
  WM_CAP_SET_PREVIEW := WM_CAP + 50
  WM_CAP_SET_PREVIEWRATE := WM_CAP + 52
  WM_CAP_SET_SCALE := WM_CAP + 53
 
  ; Connect to driver
  if SelectedDriver =
  {
    MsgBox, 16, Error!, You didn't select a video driver
    Return
  }
  SendMessage, WM_CAP_DRIVER_CONNECT, %SelectedDriver%, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ; Set the preview scale
  SendMessage, WM_CAP_SET_SCALE, 1, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ; Set the preview rate in milliseconds
  SendMessage, WM_CAP_SET_PREVIEWRATE, 66, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ; Start previewing the image from the camera
  SendMessage, WM_CAP_SET_PREVIEW, 1, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ToolTip
Return



CopyToClipBoard:
  SendMessage, WM_CAP_EDIT_COPY, 0, 0, , ahk_id %capHwnd%
Return

SenToFile:
    imagefile = C:\image.bmp
    SendMessage, WM_CAP_FILE_SAVEDIB, 0, &imagefile, , ahk_id %capHwnd%
    ToolTip % errorlevel
return


DisconnectDriver:
  SendMessage, WM_CAP_DRIVER_DISCONNECT, 1, 0, , ahk_id %capHwnd%
Return


RefreshDrivers:
  foundDriver = 0
  LV_Delete()
  Loop
  {
    thisInfo := Cap_GetDriverDescription(A_Index-1)
    If thisInfo
    {
      foundDriver = 1
      LV_Add("", A_Index-1, thisInfo)
    }
    Else
      Break
  }
  If !foundDriver
  {
    LV_Delete()
    LV_Add("", "", "Could not get video drivers")
    GuiControl, Disable, CapDriversLV
    GuiControl, Disable, SelectDriverB
  }
Return
 
 
SelectDriver:
  FocusedRowNumber := LV_GetNext(0, "F")  ; Find the focused row.
  if not FocusedRowNumber  ; No row is focused.
    return
  LV_GetText(SelectedDriver, FocusedRowNumber, 1)
Return







/*
'// The two functions exported by AVICap
Declare Function capCreateCaptureWindowA Lib "avicap32.dll" ( _
    ByVal lpszWindowName As String, _
    ByVal dwStyle As Long, _
    ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Integer, _
    ByVal hWndParent As Long, ByVal nID As Long) As Long
   
Declare Function capGetDriverDescriptionA Lib "avicap32.dll" ( _
    ByVal wDriver As Integer, _
    ByVal lpszName As String, _
    ByVal cbName As Long, _
    ByVal lpszVer As String, _
    ByVal cbVer As Long) As Boolean
*/

Cap_CreateCaptureWindow(hWndParent, x, y, w, h)
{
  WS_CHILD := 0x40000000
  WS_VISIBLE := 0x10000000
 
  lpszWindowName := "test"
 
  lwndC := DLLCall("avicap32.dll\capCreateCaptureWindowA"
                  , "Str", lpszWindowName
                  , "UInt", WS_VISIBLE | WS_CHILD ; dwStyle
                  , "Int", x
                  , "Int", y
                  , "Int", w
                  , "Int", h
                  , "UInt", hWndParent
                  , "Int", 0)
 
  ;msgbox % lwndC " | " errorlevel " | " lpszWindowName " | " hwndParent
  Return lwndC
}

Cap_GetDriverDescription(wDriver)
{
  VarSetCapacity(lpszName, 100)
  VarSetCapacity(lpszVer, 100)
  res := DLLCall("avicap32.dll\capGetDriverDescriptionA"
                  , "Short", wDriver
                  , "Str", lpszName
                  , "Int", 100
                  , "Str", lpszVer
                  , "Int", 100)
  If res
    capInfo := lpszName ; " | " lpszVer
  Return capInfo
}

GuiClose:
  GoSub, DisconnectDriver
  DllCall("FreeLibrary", "str", hModule)
  ExitApp
Return

!r::Reload ; for debugging

Hope this helps
Posted Image

goldensoft
  • Members
  • 11 posts
  • Last active: Oct 17 2007 07:04 PM
  • Joined: 23 Jul 2007
Micahs the code that you created is just perfect, it seems that 3 days of frustrating work have finally ended. Just wants to tell You THANK YOU!

Now about the script anyone knows how to directly from the script we can save a jpeg webcam shot with quality of 20? I'm not referring to save first the bmp/dib image and then convert it to jpg. What I mean is convert it directly from an image variable (not clipboard) stored in the script to a jpeg file?

Micahs
  • Members
  • 463 posts
  • Last active: Mar 01 2013 06:01 AM
  • Joined: 01 Dec 2006
The quick and dirty way:
Use this util - kiu-clipsave
"WM_CAP_GRAB_FRAME_NOSTOP" captures the current frame to the clipboard and "kiu-clipsave" saves it as a jpg and png.
SenToFile:
	saveas = JPG	;or BMP
	If(saveas = "JPG")	;save as jpg
	{
		SendMessage, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0, , ahk_id %capHwnd%	;copies to clipboard
		RunWait, kiu-clipsave.exe	;copies from clipboard to file
	}
	Else	;save as bmp
	{
		imagefile = C:\image.bmp
		SendMessage, WM_CAP_FILE_SAVEDIB, 0, &imagefile, , ahk_id %capHwnd%
		ToolTip % errorlevel
    }
return

Harder and slower way:
http://www.autohotke...pic.php?t=11860
http://www.autohotke...pic.php?t=12012
Figure out how to capture just the "ClsCapWin1" area and save that hdc to a jpg.
Posted Image

Micahs
  • Members
  • 463 posts
  • Last active: Mar 01 2013 06:01 AM
  • Joined: 01 Dec 2006
Ok, I think I've got this one licked. Building on the work of PhiLho, daonlyfreez, and holomind, Here you go:

This captures the ClsCapWin1 (with the webcam script running) and saves it as a jpg. Here is the original.
You also need GDIPlusHelper.ahk. This is an amalgam by holomind of PhiLho's GDI stuff from here.

Have both scripts running and press win-v to create the image. It will be in the "screens" directory.
You will probably want to incorporate the relevant portions of this into the webcam script. Have fun!
#Include GDIPlusHelper.ahk
; see: http://www.autohotkey.com/forum/viewtopic.php?t=11860 for orignal

capWidth = 320
capHeight = 240

OnExit, handle_exit

main: 
  FileCreateDir, screens
  FileCreateDir, thumbs

  ;WinGet, hw_frame, id, "Program Manager"   ; Desktop ?
  ControlGet,hw_frame,Hwnd,,ClsCapWin1,Video For Windows for AutoHotkey - VFW4AHK
  hdc_frame := DllCall( "GetDC", "uint",  hw_frame )
  hdc_frame_full := DllCall( "GetDC", "uint",  hw_frame )
  counter:=0   ; thumbnails
  counter_f:=0   ; fullscreens
  thumb_w:= 200 
  thumb_h:= ceil( thumb_w * capHeight / capWidth ) ; keep screenratio
  use_antialize := 1
  

  ; buffer
  hdc_buffer := DllCall( "gdi32.dll\CreateCompatibleDC"     , "uint", hdc_frame )
  hbm_buffer := DllCall( "gdi32.dll\CreateCompatibleBitmap" , "uint", hdc_frame, "int", thumb_w, "int", thumb_h )
  r          := DllCall( "gdi32.dll\SelectObject"           , "uint", hdc_buffer, "uint", hbm_buffer )

  hdc_buffer_full := DllCall( "gdi32.dll\CreateCompatibleDC"     , "uint", hdc_frame_full )
  hbm_buffer_full := DllCall( "gdi32.dll\CreateCompatibleBitmap" , "uint", hdc_frame_full, "int", capWidth, "int", capHeight )
  r_full          := DllCall( "gdi32.dll\SelectObject"           , "uint", hdc_buffer_full, "uint", hbm_buffer_full )

  ; comment this line for speed but less quality
  if use_antialize = 1
    DllCall( "gdi32.dll\SetStretchBltMode", "uint", hdc_buffer, "int", 4 )  ; Halftone better quality with stretch

return

#c::
SaveImage:
  counter := counter +1
  FormatTime, myTime, , yyyyMMdd_hhmmss
  fileNameDestP = thumbs\T_%myTime%_%counter%_%thumb_w%x%thumb_h%.jpg

  If (GDIplus_Start() != 0)
     Goto GDIplusError

  ; Copy BMP from DC
  DllCall( "gdi32.dll\StretchBlt" 
          , "uint", hdc_buffer, "int", 0, "int", 0, "int", thumb_w, "int", thumb_h
          , "uint", hdc_frame,  "int", 0, "int", 0, "int", capWidth, "int", capHeight, "uint", 0x00CC0020 )

  DllCall( "GDIplus\GdipCreateBitmapFromHBITMAP", uint, hbm_buffer, uint, 0, uintp, bitmap )

  ; Save to PNG

  ;If (GDIplus_GetEncoderCLSID(pngEncoder, #GDIplus_mimeType_png) != 0)
  If (GDIplus_GetEncoderCLSID(jpgEncoder, #GDIplus_mimeType_jpg) != 0)
     Goto GDIplusError

  noParams = NONE
  ;If (GDIplus_SaveImage(bitmap, fileNameDestP, pngEncoder, noParams) != 0)
  If (GDIplus_SaveImage(bitmap, fileNameDestP, jpgEncoder, noParams) != 0)
     Goto GDIplusError
   Gosub GDIplusStop
Return 

#v::
SaveImage_Full:
  counter_f := counter_f +1
  FormatTime, myTime, , yyyyMMdd_hhmmss
  fileNameDestP = screens\S_%myTime%_%counter_f%_%capWidth%x%capHeight%.jpg

  If (GDIplus_Start() != 0)
     Goto GDIplusError

  ; Copy BMP from DC
  DllCall( "gdi32.dll\BitBlt" 
          , "uint", hdc_buffer_full, "int", 0, "int", 0, "int", capWidth, "int", capHeight
          , "uint", hdc_frame_full,  "int", 0, "int", 0, "uint", 0x00CC0020 )

  DllCall( "GDIplus\GdipCreateBitmapFromHBITMAP", uint, hbm_buffer_full, uint, 0, uintp, bitmap )

  ; Save to JPG

  If (GDIplus_GetEncoderCLSID(jpgEncoder, #GDIplus_mimeType_jpg) != 0)
     Goto GDIplusError

  noParams = NONE
  If (GDIplus_SaveImage(bitmap, fileNameDestP, jpgEncoder, noParams) != 0)
     Goto GDIplusError
   Gosub GDIplusStop
Return 

GDIplusError:
GDIplusStop:
   If (#GDIplus_lastError != "")
      MsgBox 16, GDIplus Test, Error in %#GDIplus_lastError%
   GDIplus_Stop()
Return

#x::
handle_exit:
   DllCall( "gdi32.dll\DeleteObject", "uint", hbm_buffer )
   DllCall( "gdi32.dll\DeleteDC"    , "uint", hdc_frame )
   DllCall( "gdi32.dll\DeleteDC"    , "uint", hdc_buffer )
ExitApp

Oh, you'll have to look at the options of the GDIPlus script to change the quality of the final jpg.
Posted Image

stressbaby
  • Members
  • 153 posts
  • Last active: Aug 10 2015 09:41 PM
  • Joined: 17 Aug 2009
Old thread, giving a bump. This script seems to work really well for my purpose.

I have combined Micahs working version with his "save as JPG" script.

I would like to be able for my staff to skip the "select a driver" step. I would like to create a second GUI which would appear on first run of the script; this would write an ini file, then the script would read that information on subsequent runs. I'm struggling with this question: Which driver elements or variables need to be stored in the ini file to be able to successfully run the script without selecting the driver each time? Can this be done?

Thanks in advance.

;
; AutoHotkey Version: 1.x
; Language:       English
; Platform:       Win9x/NT
; Author:         A.N.Other <[email protected]>
;
; Script Function:
;	Template script (you can customize this template by editing "ShellNew\Template.ahk" in your Windows folder)
;

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance force
#Include GDIPlusHelper.ahk

capWidth = 320
capHeight = 240

OnExit, handle_exit

; http://ej.bantz.com/video/
; http://ej.bantz.com/video/detail/
; http://www.dotnet4all.com/dotnet-code/2004/12/video-capture.html


; Basic Demo - v 0.2

hModule := DllCall("LoadLibrary", "str", "avicap32.dll")

Gui, Add, GroupBox, x4 y4 w492 h100, Available Video Drivers
Gui, Add, ListView, x8 y20 w400 h80 vCapDriversLV, Index|Name
Gui, Add, Picture, x434 y16 w32 h32 Icon204, %A_WinDir%\system32\shell32.dll
Gui, Add, Button, x412 y50 w80 h24 gRefreshDrivers, Refresh
Gui, Add, Button, x412 y76 w80 h24 gSelectDriver vSelectDriverB, Select


; --- Video preview section of Gui
Gui, Add, GroupBox, x4 y108 w492 h262, Video

; Video preview placeholder
Gui, Add, Text, x10 y124 w320 h240 vVidPlaceholder
GuiControl, +0x7, VidPlaceholder ; frame
Gui, Font, s32
Gui, Add, Text, x32 y200 w280 h64 Center, Preview
Gui, Font

Gui, Add, CheckBox, x340 y120 w100 h24 vPreviewToggleState gPreviewToggle, Preview video
;Gui, Add, Button, x440 y120 w50 h24 gCopyToClipBoard, Copy
Gui, Add, Button, x400 y160 w90 h24 gSenToFile, Save as &BMP
Gui, Add, Button, x400 y190 w90 h24 gSaveAsJPG, Save as &JPG



; --- Statusbar
Gui, Add, StatusBar,, Done
SB_SetIcon("shell32.dll", 222, 1)

; Get drivers
GoSub, RefreshDrivers

; Get handle of Gui
Gui +LastFound
hwndParent := WinExist()

; Show
Gui, Show, w500 h400, Video For Windows for AutoHotkey - VFW4AHK

return


PreviewToggle:
;msgbox Only once!
;  If PreviewToggleState
    GoSub ConnectToDriver
;  Else
;    GoSub DisconnectDriver
Return


ConnectToDriver:
  ; --- Connect and preview
  capHwnd := Cap_CreateCaptureWindow(hwndParent, 10, 124, 320, 240)
  ;ToolTip % errorlevel
 

  WM_USER = 0x0400
  WM_CAP_START := WM_USER
  WM_CAP_GRAB_FRAME_NOSTOP := WM_USER + 61
  WM_CAP_FILE_SAVEDIB := WM_CAP_START + 25


  WM_CAP := 0x400
  WM_CAP_DRIVER_CONNECT := WM_CAP + 10
  WM_CAP_DRIVER_DISCONNECT := WM_CAP + 11
  WM_CAP_EDIT_COPY := WM_CAP + 30
  WM_CAP_SET_PREVIEW := WM_CAP + 50
  WM_CAP_SET_PREVIEWRATE := WM_CAP + 52
  WM_CAP_SET_SCALE := WM_CAP + 53
 
  ; Connect to driver
  if SelectedDriver =
  {
    MsgBox, 16, Error!, You didn't select a video driver
    Return
  }
  SendMessage, WM_CAP_DRIVER_CONNECT, %SelectedDriver%, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ; Set the preview scale
  SendMessage, WM_CAP_SET_SCALE, 1, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ; Set the preview rate in milliseconds
  SendMessage, WM_CAP_SET_PREVIEWRATE, 66, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ; Start previewing the image from the camera
  SendMessage, WM_CAP_SET_PREVIEW, 1, 0, , ahk_id %capHwnd%
  ;ToolTip % errorlevel
 
  ToolTip
Return



CopyToClipBoard:
  SendMessage, WM_CAP_EDIT_COPY, 0, 0, , ahk_id %capHwnd%
Return

SenToFile:
    imagefile = %A_Desktop%\image
    SendMessage, WM_CAP_FILE_SAVEDIB, 0, &imagefile, , ahk_id %capHwnd%
    ;ToolTip % errorlevel
return


DisconnectDriver:
  SendMessage, WM_CAP_DRIVER_DISCONNECT, 1, 0, , ahk_id %capHwnd%
Return


RefreshDrivers:
  foundDriver = 0
  LV_Delete()
  Loop
  {
    thisInfo := Cap_GetDriverDescription(A_Index-1)
    If thisInfo
    {
      foundDriver = 1
      LV_Add("", A_Index-1, thisInfo)
    }
    Else
      Break
  }
  If !foundDriver
  {
    LV_Delete()
    LV_Add("", "", "Could not get video drivers")
    GuiControl, Disable, CapDriversLV
    GuiControl, Disable, SelectDriverB
  }
Return
 
 
SelectDriver:
  FocusedRowNumber := LV_GetNext(0, "F")  ; Find the focused row.
  if not FocusedRowNumber  ; No row is focused.
    return
  LV_GetText(SelectedDriver, FocusedRowNumber, 1)
Return

SaveAsJPG:
  FileCreateDir, screens
  FileCreateDir, thumbs
  ;WinGet, hw_frame, id, "Program Manager"   ; Desktop ?
  ControlGet,hw_frame,Hwnd,,ClsCapWin1,Video For Windows for AutoHotkey - VFW4AHK
  hdc_frame := DllCall( "GetDC", "uint",  hw_frame )
  hdc_frame_full := DllCall( "GetDC", "uint",  hw_frame )
  counter:=0   ; thumbnails
  counter_f:=0   ; fullscreens
  thumb_w:= 200
  thumb_h:= ceil( thumb_w * capHeight / capWidth ) ; keep screenratio
  use_antialize := 1
 

  ; buffer
  hdc_buffer := DllCall( "gdi32.dll\CreateCompatibleDC"     , "uint", hdc_frame )
  hbm_buffer := DllCall( "gdi32.dll\CreateCompatibleBitmap" , "uint", hdc_frame, "int", thumb_w, "int", 

thumb_h )
  r          := DllCall( "gdi32.dll\SelectObject"           , "uint", hdc_buffer, "uint", hbm_buffer )

  hdc_buffer_full := DllCall( "gdi32.dll\CreateCompatibleDC"     , "uint", hdc_frame_full )
  hbm_buffer_full := DllCall( "gdi32.dll\CreateCompatibleBitmap" , "uint", hdc_frame_full, "int", capWidth, 

"int", capHeight )
  r_full          := DllCall( "gdi32.dll\SelectObject"           , "uint", hdc_buffer_full, "uint", 

hbm_buffer_full )

  ; comment this line for speed but less quality
  if use_antialize = 1
    DllCall( "gdi32.dll\SetStretchBltMode", "uint", hdc_buffer, "int", 4 )  ; Halftone better quality with 

stretch

SaveImage_Full:
  counter_f := counter_f +1
  FormatTime, myTime, , yyyyMMdd_hhmmss
  fileNameDestP = screens\S_%myTime%_%counter_f%_%capWidth%x%capHeight%.jpg

  If (GDIplus_Start() != 0)
     Goto GDIplusError

  ; Copy BMP from DC
  DllCall( "gdi32.dll\BitBlt"
          , "uint", hdc_buffer_full, "int", 0, "int", 0, "int", capWidth, "int", capHeight
          , "uint", hdc_frame_full,  "int", 0, "int", 0, "uint", 0x00CC0020 )

  DllCall( "GDIplus\GdipCreateBitmapFromHBITMAP", uint, hbm_buffer_full, uint, 0, uintp, bitmap )

  ; Save to JPG

  If (GDIplus_GetEncoderCLSID(jpgEncoder, #GDIplus_mimeType_jpg) != 0)
     Goto GDIplusError

  noParams = NONE
  If (GDIplus_SaveImage(bitmap, fileNameDestP, jpgEncoder, noParams) != 0)
     Goto GDIplusError
   Gosub GDIplusStop
Return



Cap_CreateCaptureWindow(hWndParent, x, y, w, h)
{
  WS_CHILD := 0x40000000
  WS_VISIBLE := 0x10000000
 
  lpszWindowName := "test"
 
  lwndC := DLLCall("avicap32.dll\capCreateCaptureWindowA"
                  , "Str", lpszWindowName
                  , "UInt", WS_VISIBLE | WS_CHILD ; dwStyle
                  , "Int", x
                  , "Int", y
                  , "Int", w
                  , "Int", h
                  , "UInt", hWndParent
                  , "Int", 0)
 
  ;msgbox % lwndC " | " errorlevel " | " lpszWindowName " | " hwndParent
  Return lwndC
}

Cap_GetDriverDescription(wDriver)
{
  VarSetCapacity(lpszName, 100)
  VarSetCapacity(lpszVer, 100)
  res := DLLCall("avicap32.dll\capGetDriverDescriptionA"
                  , "Short", wDriver
                  , "Str", lpszName
                  , "Int", 100
                  , "Str", lpszVer
                  , "Int", 100)
  If res
    capInfo := lpszName ; " | " lpszVer
  Return capInfo
}

GuiClose:
  GoSub, DisconnectDriver
  DllCall("FreeLibrary", "str", hModule)
  ExitApp
Return

!r::Reload ; for debugging

GDIplusError:
GDIplusStop:
   If (#GDIplus_lastError != "")
      MsgBox 16, GDIplus Test, Error in %#GDIplus_lastError%
   GDIplus_Stop()
Return

handle_exit:
   DllCall( "gdi32.dll\DeleteObject", "uint", hbm_buffer )
   DllCall( "gdi32.dll\DeleteDC"    , "uint", hdc_frame )
   DllCall( "gdi32.dll\DeleteDC"    , "uint", hdc_buffer )
ExitApp


Micahs
  • Members
  • 463 posts
  • Last active: Mar 01 2013 06:01 AM
  • Joined: 01 Dec 2006
From looking at the source, and it has been a long time, I would say that you need the 'SelectedDriver' var.

On first run, show the driver select gui and save the 'SelectedDriver' var. On subsequent runs, instead of having them select a driver and click the 'Select Driver' button, just readini the 'SelectedDriver' var back in. This will prevent having to select a driver each time, but will not help with having to choose the source each time. Of course, this depends on if your driver requires that to be selected...

HTH
Posted Image

stressbaby
  • Members
  • 153 posts
  • Last active: Aug 10 2015 09:41 PM
  • Joined: 17 Aug 2009
Thank you for your reply micahs.

I tried that, and several variations. SelectedDriver stores as it's index, which generally is zero (0). Some variations yield a "Microsoft Error" when I load the script the second time, reading "SelectedDriver=0" from the ini file. Others just result in failure to see the image.

What I'm thinking is that after I destroy the second GUI, the one with the List View and which writes the ini file, that the reference is lost, and the ConnectToDriver subroutine fails. I tried adding hwndParent and of course I can get that written to the ini file, but I can't read that back successfully.