本人用 VB 基于WM Encoder写了一段录屏程序。在单显示的情况下没有问题,CPU占用不高,用户没有什么感觉。但是在双显示器的情况下,程序把主副显示器的内容都录制了,导致CPU占用高达90%以上,客户程序无法正常运行。看了SDK ,想用指定录制区域的方法解决这个问题。但是SDK 只提供了C++的方法。有高手能帮我转为VB能用的程序吗?多谢。
VB 实现代码如下:  ' Create a WMEncoder object.
    Set Encoder = New WMEncoder
  
    ' Retrieve the source group collection and add a source group.
    Dim SrcGrpColl As IWMEncSourceGroupCollection
    Set SrcGrpColl = Encoder.SourceGroupCollection
    Dim SrcGrp As IWMEncSourceGroup2
    Set SrcGrp = SrcGrpColl.Add("SG_1")
    
    ' Add a video and audio source to the source group.
    Dim SrcVid As IWMEncVideoSource
    'Dim SrcAud As IWMEncAudioSource
    Set SrcVid = SrcGrp.AddSource(WMENC_VIDEO)
'    Set SrcAud = SrcGrp.AddSource(WMENC_AUDIO)
    
    ' Identify the source files to encode.
    SrcVid.SetInput "ScreenCap://ScreenCapture1"    ' Choose a profile from the collection.
    Dim ProColl As IWMEncProfileCollection
    Dim Pro As IWMEncProfile
    Dim i As Integer
    Dim lLength As Long    Set ProColl = Encoder.ProfileCollection
    lLength = ProColl.Count    For i = 0 To lLength - 1
        Set Pro = ProColl.Item(i)
        Debug.Print Pro.Name
        If Pro.Name = "屏幕视频 - 中(CBR)" Then
            SrcGrp.Profile = Pro
            Exit For
        End If
    Next
    
    ' Fill in the description object members.
    Dim Descr As IWMEncDisplayInfo
    Set Descr = Encoder.DisplayInfo
    Descr.Author = "Author name"
    Descr.Copyright = "Copyright information"
    Descr.Description = "Text description of encoded content"
    Descr.Rating = "Rating information"
    Descr.Title = "Title of encoded content"
       
    ' Specify a file object in which to save encoded content.
    Dim File As IWMEncFile
    Set File = Encoder.File
    File.LocalFileName = "C:\\OutputFile.wmv"
      
    ' Start the encoding process.
    Encoder.Start SDK中C++选择区域的方法为:
    // Include libraries.
#include <windows.h>
#include <atlbase.h>
#include <comdef.h>
#include "C:\WMSDK\WMEncSDK9\include\wmencode.h"// Define the screen capture properties.
#define WMSCRNCAP_CAPTUREWINDOW     CComBSTR("CaptureWindow")
#define WMSCRNCAP_WINDOWLEFT        CComBSTR("Left")
#define WMSCRNCAP_WINDOWTOP         CComBSTR("Top")
#define WMSCRNCAP_WINDOWRIGHT       CComBSTR("Right")
#define WMSCRNCAP_WINDOWBOTTOM      CComBSTR("Bottom")
#define WMSCRNCAP_FLASHRECT         CComBSTR("FlashRect")
#define WMSCRNCAP_ENTIRESCREEN      CComBSTR("Screen")
#define WMSCRNCAP_WINDOWTITLE       CComBSTR("WindowTitle")// Declare variables.
HRESULT hr = S_OK;
IWMEncoder* pEncoder;
IWMEncSourceGroupCollection* pSrcGrpColl;
IWMEncSourceGroup* pSrcGrp;
IWMEncSource* pSrc;
IWMEncVideoSource2* pSrcVid;
IPropertyBag* pPropertyBag;
CComVariant varValue;// Initialize the COM library and retrieve a pointer to an IWMEncoder interface.
hr = CoInitialize(NULL);
if ( SUCCEEDED( hr ) )
{
    hr = CoCreateInstance(CLSID_WMEncoder,
        NULL,
        CLSCTX_INPROC_SERVER,
        IID_IWMEncoder,
        (void**) &pEncoder);
}// Retrieve the source group collection.
if ( SUCCEEDED( hr ) )
{
    hr = pEncoder->get_SourceGroupCollection(&pSrcGrpColl);
}// Add a source group to the collection.
if ( SUCCEEDED( hr ) )
{
    hr = pSrcGrpColl->Add(CComBSTR("SG_1"), &pSrcGrp);
}
if ( SUCCEEDED( hr ) )
{
    hr = pSrcGrp->AddSource(WMENC_VIDEO, &pSrc);
}// Retrieve an IWMEncVideoSource2 pointer.
if ( SUCCEEDED( hr ) )
{
    hr = pSrc->QueryInterface(IID_IWMEncVideoSource2, (void**)&pSrcVid);
}// Add a video source to the source group.
if ( SUCCEEDED( hr ) )
{
    hr = pSrcVid->SetInput(CComBSTR("ScreenCap://ScreenCapture1"));
}// Retrieve a pointer to the property bag.
if ( SUCCEEDED( hr ) )
{
    hr = pSrcVid->QueryInterface(IID_IPropertyBag, (void**)&pPropertyBag);
}// Set full screen capture.
{
    varValue = true;
    if ( SUCCEEDED( hr ) )
    {
        hr = pPropertyBag->Write( WMSCRNCAP_ENTIRESCREEN, &varValue );
    }
}// Set the capture area.
{
    // nLeft, nRight, nTop, and nBottom are the dimensions to capture
    int nLeft, nRight, nTop, nBottom;    // Initialize the capture area. The size must be even.
    varValue = false;
    if ( SUCCEEDED( hr ) )
    {
        hr = pPropertyBag->Write( WMSCRNCAP_ENTIRESCREEN, &varValue );
    }    varValue = nLeft;
    if ( SUCCEEDED( hr ) )
    {
        hr = pPropertyBag->Write( WMSCRNCAP_WINDOWLEFT, &varValue );
    }    varValue = nRight;
    if ( SUCCEEDED( hr ) )
    {
        hr = pPropertyBag->Write( WMSCRNCAP_WINDOWRIGHT, &varValue );
    }    varValue = nTop;
    if ( SUCCEEDED( hr ) )
    {
        hr = pPropertyBag->Write( WMSCRNCAP_WINDOWTOP, &varValue );
    }    varValue = nBottom;
    if ( SUCCEEDED( hr ) )
    {
        hr = pPropertyBag->Write( WMSCRNCAP_WINDOWBOTTOM, &varValue );
    }    varValue = true;
    if ( SUCCEEDED( hr ) )
    {
        hr = pPropertyBag->Write( WMSCRNCAP_FLASHRECT, &varValue );
    }    自己试着写了点VB转换的代码,总是实现不了,希望高人帮帮忙。急啊!!!!
    万分感谢!!!!

解决方案 »

  1.   

    1.将显卡的硬件加速设为0
    2.使用单独的进程实现录屏
    3.将录制屏幕的切割参数left设定为整个屏幕的一半。
    目前使用这种方法程序可以使用了。。
    虽然没有得到想要的方法。但是还是感谢Veron_04
      

  2.   

    大致看了一下,估计是这样
    SrcVid.SetInput "ScreenCap://ScreenCapture1"
    srcvid.IPropertyBag
    IPropertyBag.WMSCRNCAP_ENTIRESCREEN=false
    IPropertyBag.left=
    IPropertyBag.top=
    IPropertyBag.right=
    IPropertyBag.bottom=
      

  3.   

    Srcvid没有IPropertybag
    而且在VB里面设置一个IPropertybag后。只能用写属性和读属性给属性页赋值。
    Dim Ipor As PropertyBag
    Ipor.ReadProperty
    Ipor.WriteProperty
    我按照C++的赋值方法对相应属性赋值
    #define WMSCRNCAP_CAPTUREWINDOW CComBSTR("CaptureWindow")
    #define WMSCRNCAP_WINDOWLEFT CComBSTR("Left")
    #define WMSCRNCAP_WINDOWTOP CComBSTR("Top")
    #define WMSCRNCAP_WINDOWRIGHT CComBSTR("Right")
    #define WMSCRNCAP_WINDOWBOTTOM CComBSTR("Bottom")
    #define WMSCRNCAP_FLASHRECT CComBSTR("FlashRect")
    #define WMSCRNCAP_ENTIRESCREEN CComBSTR("Screen")
    #define WMSCRNCAP_WINDOWTITLE CComBSTR("WindowTitle")
    比如
    Ipor.WriteProperty "Left", 20
    但是设置完以后没有什么反应呵呵。求解!