Jump to content

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

Add VFW - Video for Windows to AHK GUI! [WORKS (somewhat)]


  • Please log in to reply
33 replies to this topic
daonlyfreez
  • Members
  • 995 posts
  • Last active: Jan 23 2013 08:16 AM
  • Joined: 16 Mar 2005
Been trying to add a webcam/VFW control to an AHK Gui...

However, this crashes on me on the capCreateCaptureWindowA call...

:?

What am I doing wrong? Anybody?

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


Gui, Add, ListView, vCapDriversLV, Index|Name


;Gui, Add, Picture, w320 h240 HWNDhwndParent, C:\WINDOWS\winnt.bmp


Gui +LastFound
hwndParent := WinExist()
Gui, Show, w500 h400

msgbox Scanning available Webcam drivers...

Loop
{
  thisInfo := Cap_GetDriverDescription(A_Index-1)
  If thisInfo
    LV_Add("", A_Index-1, thisInfo)
  Else
    Break
}

msgbox Create capture window... (this crashes)

capHwnd := Cap_CreateCaptureWindow(hwndParent, 0, 0, 320, 240)

msgbox % capHwnd

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 
}

!r::Reload

GuiClose:

ExitApp
Return

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

engunneer
  • Moderators
  • 9162 posts
  • Last active: Sep 12 2014 10:36 PM
  • Joined: 30 Aug 2005
I don't have my webcam at work, so I'll have to try this later (if i can find it!) I am interested in the theory though, it seems useful to be able to do.

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
A few of us still should like to know, why this script crashes. According to MSDN, it is how we should create AVICap capture windows, which are special controls. There must be something incompatible with AHK. Here is a minimal script, which should work, but crashes.
MsgBox % Cap_CreateCaptureWindow(WinExist("ahk_class Progman"), 0, 0, 160, 120)



Cap_CreateCaptureWindow(hWndParent, x, y, w, h) {

  Return DLLCall("avicap32.dll\capCreateCaptureWindowA" ; -> Long

                , "Str", "test"                         ; lpszWindowName  String

                , "UInt",0x40000000|0x10000000          ; dwStyle         Long  WS_CHILD|WS_VISIBLE

                , "Int", x                              ; x               Long

                , "Int", y                              ; y               Long

                , "Int", w                              ; nWidth          Long

                , "Int", h                              ; nHeight         Integer

                , "Int", hWndParent                     ; hWndParent      Long

                , "Int", 0)                             ; nID             Long

}
Any information is appreciated…

Zippo()
  • Guests
  • Last active:
  • Joined: --
Changing it a little, I got it to wait until you close the script before it crashes by adding a GUI. :D

Gui, Show, w100 h100, Test
WinGet, hWndParent, ID, Test
WinGetPos, x, y, w, h, Test


cap := Cap_CreateCaptureWindow(hWndParent, x, y, w, h) 
Return

Cap_CreateCaptureWindow(hWndParent, x, y, w, h) { 
  Return DLLCall("avicap32.dll\capCreateCaptureWindowA" ; -> Long 
                , "Str", "test"                         ; lpszWindowName  String 
                , "UInt",0x40000000|0x10000000          ; dwStyle         Long  WS_CHILD|WS_VISIBLE 
                , "Int", x                              ; x               Long 
                , "Int", y                              ; y               Long 
                , "Int", w                              ; nWidth          Long 
                , "Int", h                              ; nHeight         Integer 
                , "Int", hWndParent                     ; hWndParent      Long 
                , "Int", 0)                             ; nID             Long 
}
Didn't like the message box I guess.

Anyhow, I don't have a web can on this machine, but here is a page that looks pretty easy to understand (if you haven't seen it already):

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

Zippo()
  • Guests
  • Last active:
  • Joined: --
P.S...

You can check that it is returning from the call by doing ToolTip % cap before the Return.

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007
Looks like it's one of the frequently forgotten things. Add the following code at the start of the script.

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


Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005

Didn't like the message box I guess.

I tried ToolTip, TrayTip, MsgBox, Send {LWin}… The script does not return from the capCreateCaptureWindowA dll call.

Anyhow, I don't have a web can on this machine

You don't need one. This dll call just should create a child window (a control), which can be used later for video.

Looks like it's one of the frequently forgotten things…

Thanks! That's it. No crash any more! But why is it necessary? Does the capCreateCaptureWindowA call other dll functions, which are not found without loading the library?

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007

That's it. No crash any more! But why is it necessary? Does the capCreateCaptureWindowA call other dll functions, which are not found without loading the library?

I think the situation is similar to this:
<!-- m -->http://www.autohotke...pic.php?t=17831<!-- m -->

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
Chris: could you add a sentence to the LoadLibrary section at the dllcall documentation explaining that LoadLibrary is often necessary to keep internal data structures alive and to help finding functions, which are indirectly called in the library? It looks like a common theme.

Zippo()
  • Guests
  • Last active:
  • Joined: --

I tried ToolTip, TrayTip, MsgBox, Send {LWin}… The script does not return from the capCreateCaptureWindowA dll call.


That is interesting. With this:
CoordMode, ToolTip, Screen
Gui, Show, w100 h100, Test 
WinGet, hWndParent, ID, Test 
WinGetPos, x, y, w, h, Test 


cap := Cap_CreateCaptureWindow(hWndParent, x, y, w, h) 
ToolTip, %cap%, x+5, y+50
Return 

Cap_CreateCaptureWindow(hWndParent, x, y, w, h) { 
  Return DLLCall("avicap32.dll\capCreateCaptureWindowA" ; -> Long 
                , "Str", "test"                         ; lpszWindowName  String 
                , "UInt",0x40000000|0x10000000          ; dwStyle         Long  WS_CHILD|WS_VISIBLE 
                , "Int", x                              ; x               Long 
                , "Int", y                              ; y               Long 
                , "Int", w                              ; nWidth          Long 
                , "Int", h                              ; nHeight         Integer 
                , "Int", hWndParent                     ; hWndParent      Long 
                , "Int", 0)                             ; nID             Long 
}
I get this:
Posted Image

...

But the LoadLibrary works for me too. Thanks Sean :)

daonlyfreez
  • Members
  • 995 posts
  • Last active: Jan 23 2013 08:16 AM
  • Joined: 16 Mar 2005
Alright! Works somewhat! 8)

Posted Image

It's far from finished, but you can take a shot at it with my preliminary code if you like.

First, select the driver to use (select in list, then click select button)
Second, check the preview video checkbox (Do this only once! As said, the code is preliminary :shock: )

If you click on the copy button, a picture/cap is sent to the clipboard

No time left for now, will continue later :wink:

; 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

/*
; --- 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

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

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

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
Works just fine! Finally, a pure AHK video capture! Thanks for sharing it!

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007

Alright! Works somewhat! 8)

Excellent. It's too bad that I don't have a webcam.

engunneer
  • Moderators
  • 9162 posts
  • Last active: Sep 12 2014 10:36 PM
  • Joined: 30 Aug 2005
it doesn't turn on my laptop's built in camera. Oh, well.

n-l-i-d
  • Guests
  • Last active:
  • Joined: --
I'm having serious troubles with my old VFW cam. Too bad this doesn't support 2nd generation cams (WDM - Windows Direct Media, DirectX/DirectShow).

Can anyone confirm this keeps working? It crashes on me after a while, but I guess that is because I'm having general troubles connecting to my very-old-and-dusty-USB-VFW-cam... :?