thenetfreaker has asked for the wisdom of the Perl Monks concerning the following question:

Hello dear monks,
I'm building a screensaver like program in perl for Win32,
my main concern is the correct implementation of multiple API calls like Visual-Basic.
The following code is supposed to take a PrintScreen, open a fullscreen "window" and "draw" the bitmap from the clipboard in the window :

ApiLink( 'user32.dll', 'Private Declare Sub keybd_event Lib "user32" ( +ByVal bVk As Byte, _ ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As L +ong)' ) or die $^E; ApiLink( 'user32.dll', 'Private Const KEYEVENTF_KEYUP = &H2' ) or +die $^E; ApiLink( 'user32.dll', 'Function GetScreenBitmap() As Picture' ) o +r die $^E; ApiLink( 'user32.dll', 'Dim pic As StdPicture' ) or die $^E; ApiLink( 'user32.dll', 'Set pic = Clipboard.GetData(vbCFBitmap)' ) + or die $^E; ApiLink( 'user32.dll', 'keybd_event vbKeySnapshot, 0, 0, 0' ) or d +ie $^E; ApiLink( 'user32.dll', 'DoEvents' ) or die $^E; ApiLink( 'user32.dll', 'keybd_event vbKeySnapshot, 0, KEYEVENTF_KE +YUP, 0' ) or die $^E; ApiLink( 'user32.dll', 'DoEvents' ) or die $^E; ApiLink( 'user32.dll', 'Set GetScreenBitmap = Clipboard.GetData(vb +CFBitmap)' ) or die $^E; ApiLink( 'user32.dll', 'Clipboard.SetData pic, vbCFBitmap' ) or di +e $^E; ApiLink( 'user32.dll', 'End Function' ) or die $^E; ApiLink( 'user32.dll', 'Set Picture1.Picture = GenScreenBitmap()' +) or die $^E; ApiLink( 'user32.dll', 'this.Size = new System.Drawing.Size(width, + height)' ) or die $^E; ApiLink( 'user32.dll', 'this.Setstyle(Controlstyles.DoubleBuffer | + Controlstyles.UserPaint |Controlstyles.AllPaintingInWmPaint | Contro +lstyles.FixedWidth |Controlstyles.FixedHeight, true)' ) or die $^E; ApiLink( 'user32.dll', 'this.Updatestyles()' ) or die $^E; ApiLink( 'user32.dll', 'this.FormBorderstyle = FormBorderstyle.Non +e' ) or die $^E; ApiLink( 'user32.dll', 'this.TopMost = true' ) or die $^E; ApiLink( 'user32.dll', 'this.StartPosition = FormStartPosition.Cen +terScreen' ) or die $^E; ApiLink( 'user32.dll', 'this.ClientSize = new System.Drawing.Size( +width, height)' ) or die $^E; ApiLink( 'user32.dll', 'this.Location = this.DesktopLocation = new + System.Drawing.Point(0, 0)' ) or die $^E; ApiLink( 'user32.dll', 'public void bitBlt(Picture1, 0, 0)' ) or d +ie $^E;

Therefore the first question is if i'm using Win32::API correctly ?
The second question would be - if it's possible to join all these lines into one code (VB / .Net / C++) ?

Replies are listed 'Best First'.
Re: Multiple API calls
by Corion (Patriarch) on Oct 25, 2007 at 09:17 UTC

    Without seeing what ApiLink is, and where it comes from, it's hard to tell whether your code is correct. Where do you see problems?

    I use and recommend Win32::API for interfacing with the Windows API. Avoid the "prototype" variant of the API and use the "parameter list" variant, as the C parser for the "prototype" variant has given me too much grief.

    You seem to have taken some VB code and pasted it all in between calls to ApiLink() - I don't understand what this is. The Win32::API documentation does not mention ApiLink() or any way to run VB code.

    For screen grabbing, take a look at Win32::GuiTest and Win32::GuiRobot. Interfacing with the Windows API also isn't hard, but the code you show only declares one Windows API function to call, keybd_event. I would try the following to call it:

    use Win32::API; my $_keybd_event = Win32::API->new( 'user32.dll', 'keybd_event', 'IIII', 'I', ); sub keybd_event { my ($vk,$scan,$flags,$extra_info) = @_; $_keybd_event->Call($vk,$scan,$flags,$extra_info); };
Re: Multiple API calls
by almut (Canon) on Oct 25, 2007 at 09:50 UTC

    According to the documentation, the second argument to ApiLink is "the actual C prototype of the function" that you want to call.  So, feeding it successive lines of VB source code is most likely not going to work... (and I don't think there's an easy way to get it to work).

    Anyhow, as you already seem to have a VB program, why not simply run it as such? Don't get me wrong, I'd always advocate usage of Perl wherever it makes sense, but in this case it doesn't look like it would... :)

      thank you both, while waiting i've rewrote it to use SDL and also it took less (also using Win32::GuiTest)