我的程序是定时抓取活动窗体的,但是有一个很奇怪的问题!
  程序开始能抓所有的窗体,但是运行一会儿后却只能抓比较小的窗体(如任务管理器),我调试了一下,发现抓大窗体时只有一字节。这是什么原因呢?

解决方案 »

  1.   

    是不是你忘记释放内存了,我乱猜的,因为还不懂你的原理。不过你说运行一会就只能抓很小的图,我估计是你之前抓的图并没有释放内存,比如你前面new的CDC或CBitmap没有delete pTempDC;delete pTempBitmap;以上存属个人观点,不一定对,呵呵,别见笑
      

  2.   

    这是我的代码,麻烦您帮我看一下
    CMon *mon;
    mon=new CMon;
    //////////////////////////////////////////////////////////
    HWND hwnd = ::GetForegroundWindow();//获取当前窗体
    //校验窗体是否有效
    if(hwnd==NULL)
    {
    return TRUE;
    }
    if(IsWindow(hwnd)==FALSE)
    {
    return TRUE;
    }
    //获取窗口的DC和窗口的矩形信息
    HDC hsrc = ::GetWindowDC(hwnd);
    HDC hmemdc = ::CreateCompatibleDC(hsrc);
    RECT rc; 
    ::GetWindowRect(hwnd,&rc);
    HDC       hScrDC, hMemDC;      
     // 屏幕和内存设备描述表
    HBITMAP    hBitmap;   
    // 位图句柄
    int       nX, nY, nX2, nY2;      
    // 选定区域坐标
    int       nWidth, nHeight;      
    // 位图宽度和高度
    int       xScrn, yScrn;         
    // 屏幕分辨率   // 确保选定区域不为空矩形
    if (IsRectEmpty(&rc))
    return NULL;
       //为屏幕创建设备描述表
    hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
    //为屏幕设备描述表创建兼容的内存设备描述表
    hMemDC = CreateCompatibleDC(hScrDC);
        // 获得选定区域坐标
        nX = rc.left;
        nY = rc.top;
        nX2 = rc.right;
        nY2 = rc.bottom;
        // 获得屏幕分辨率
        xScrn = GetDeviceCaps(hScrDC, HORZRES);
        yScrn = GetDeviceCaps(hScrDC, VERTRES);
        //确保选定区域是可见的
        if (nX<0)
          nX = 0;
        if (nY < 0)
          nY = 0;
        if (nX2 > xScrn)
          nX2 = xScrn;
        if (nY2 > yScrn)
          nY2 = yScrn;
    nWidth = nX2 - nX;
    nHeight = nY2 - nY;
    // 创建一个与屏幕设备描述表兼容的位图
    hBitmap = CreateCompatibleBitmap
    (hScrDC, nWidth, nHeight);
    // 把新位图选到内存设备描述表中
         HGDIOBJ hOldBitmap = SelectObject(hMemDC, hBitmap);
    // 把屏幕设备描述表拷贝到内存设备描述表中
    BitBlt(hMemDC, 0, 0, nWidth, nHeight,
    hScrDC, nX, nY, SRCCOPY);
    //得到屏幕位图的句柄
    SelectObject(hMemDC, hOldBitmap);
    //清除 
        DeleteDC(hScrDC);
        DeleteDC(hMemDC);
    //////////////////////////////////
        //获取位图信息
    ////////////////////////////
    HDC hDC; //设备描述表  
        int iBits; //当前显示分辨率下每个像素所占字节数
    WORD            wBitCount; //位图中每个像素所占字节数
    DWORD           dwPaletteSize=0, //定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数
    dwBmBitsSize,
    dwDIBSize;
    BITMAP          Bitmap;        
    BITMAPFILEHEADER   bmfHdr; //位图属性结构    
        BITMAPINFOHEADER   bi; //位图文件头结构       
    LPBITMAPINFOHEADER lpbi; //位图信息头结构     
        HANDLE          hDib, hPal,hOldPal=NULL; //指向位图信息头结构,定义文件,分配内存句柄,调色板句柄
      
       //计算位图文件每个像素所占字节数
       hDC = CreateDC("DISPLAY",NULL,NULL,NULL);
       iBits = GetDeviceCaps(hDC, BITSPIXEL) * 
       GetDeviceCaps(hDC, PLANES);
       DeleteDC(hDC);
       if (iBits <= 1)
          wBitCount = 1;
       else if (iBits <= 4)
          wBitCount = 4;
       else if (iBits <= 8)
          wBitCount = 8;
       else if (iBits <= 24)
          wBitCount = 24;
       //计算调色板大小
       if (wBitCount <= 8)
          dwPaletteSize = (1 << wBitCount) *sizeof(RGBQUAD);
       
       //设置位图信息头结构
       GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
       bi.biSize            = sizeof(BITMAPINFOHEADER);
       bi.biWidth           = Bitmap.bmWidth;
       bi.biHeight          = Bitmap.bmHeight;
       bi.biPlanes          = 1;
       bi.biBitCount         = wBitCount;
       bi.biCompression      = BI_RGB;
       bi.biSizeImage        = 0;
       bi.biXPelsPerMeter     = 0;
       bi.biYPelsPerMeter     = 0;
       bi.biClrUsed         = 0;
       bi.biClrImportant      = 0;   dwBmBitsSize = ((Bitmap.bmWidth *
        wBitCount+31)/32)* 4
     *Bitmap.bmHeight ;   //为位图内容分配内存
       hDib  = GlobalAlloc(GHND,dwBmBitsSize+
    dwPaletteSize+sizeof(BITMAPINFOHEADER));
       lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
       *lpbi = bi;   // 处理调色板   
       hPal = GetStockObject(DEFAULT_PALETTE);
       if(hPal)
       {
       hDC  = ::GetDC(NULL);
       hOldPal = SelectPalette(hDC, (HPALETTE)hPal, FALSE);
           RealizePalette(hDC);
       }   // 获取该调色板下新的像素值
       int nRet=GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
     (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize,
     (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
     
       //恢复调色板   
       if (hOldPal)
       {
          SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
          RealizePalette(hDC);
          ::ReleaseDC(NULL, hDC);
       }
       
       // 设置位图文件头
       bmfHdr.bfType = 0x4D42;  // "BM"
       dwDIBSize    = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize;  
       bmfHdr.bfSize = dwDIBSize;
       bmfHdr.bfReserved1 = 0;
       bmfHdr.bfReserved2 = 0;
       bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) 
          + (DWORD)sizeof(BITMAPINFOHEADER)
         + dwPaletteSize;    int nLen,nLen1,nLen2; nLen=sizeof(BITMAPFILEHEADER);
    nLen1=sizeof(BITMAPINFOHEADER);
    nLen2=nLen+dwDIBSize;
    char *buf=new char[nLen2];
    //缓冲区分配完毕
    //开始合并缓冲区
    memmove(buf,&bmfHdr,sizeof(BITMAPFILEHEADER));
    // memmove(buf+nLen,&bi,sizeof(BITMAPINFOHEADER));
    memmove(buf+nLen,lpbi,dwDIBSize); CFile ff;
    ff.Open("cap.bmp",CFile::modeCreate|CFile::modeWrite,NULL);
    ff.Write(buf,nLen2);
    ff.Close();
    //开始转换图片类型
    CMemFile mfi,mfo;
    mfi.Attach((unsigned char*)buf,nLen2,0);
    if(!mon->MBmpToMImage(mfi,mfo,"encode/gif"))
    {
    delete mon;
    GlobalUnlock(hDib);
    GlobalFree(hDib);  
    GlobalFree(lpbi);
    delete[] buf;
    return TRUE;
    }
    //其余的省略
      

  3.   

    是下面这个问题吧,
    if(!mon->MBmpToMImage(mfi,mfo,"encode/gif"))
    {
    delete mon;
    GlobalUnlock(hDib);
    GlobalFree(hDib);  
    GlobalFree(lpbi);
    delete[] buf;
    return TRUE;
    }
    mon->MBmpToMImage(mfi,mfo,"encode/gif")函数什么意思?返回值是什么?是不是转换类型成功返回TRUE,那么返回TRUE的话,你前面加个!,if中的判断条件为假,那肯定就不会执行到下面释放内存的步骤。即你这段语句的意思是,转换不成功则执行下面的语句,转换成功反而执行不了了。不太了解你的CMon类,以及它的成员函数MBmpToMImage, 不知道我说的对不对,你把!去掉试试
      

  4.   

    它是一个转换函数将 BMP 转为 GIF 的
    函数成功了返回TRUE否则返回FALSEif(!mon->MBmpToMImage(mfi,mfo,"encode/gif"))
    {
    delete mon;
    GlobalUnlock(hDib);
    GlobalFree(hDib);  
    GlobalFree(lpbi);
    delete[] buf;
    return TRUE;
    }这句的意思是如果转换图片不成功,清除缓冲区,然后返回TRUE,用来区别数据库错误,因为数据库错误返回FALSE
      

  5.   

    帮我看一下好吗?现在看到这段代码头大
       ///////////////////////////////////////////////////////////////////////
    CString sqlstr;
    sqlstr="SELECT top 0 * FROM ScrLog ORDER BY IDNO"; if(!m_db->State)
    {
    GlobalUnlock(hDib);
            GlobalFree(hDib);  
    lpbi=NULL;
    delete[] buf;
    return FALSE;
    }
    try
    {
         HRESULT hr=m_set.CreateInstance(__uuidof(Recordset));
    if(SUCCEEDED(hr))
    {
    m_set->Open(_bstr_t(sqlstr),_variant_t((IDispatch*)m_db,true),adOpenStatic,adLockOptimistic,adCmdText);
    }
    }catch (_com_error e)
    {
    CString error="保存GIF图片时出错,错误代码:";
    error+=e.ErrorMessage();
    error+="对该错误的说明:";
    _bstr_t err=e.Description();
    error+=(LPCTSTR)err;
    SaveLog(error.GetBuffer(0));
    #ifdef _DEBUG_
    AfxMessageBox(err);
    #endif
    GlobalUnlock(hDib);
    GlobalFree(hDib);  
    lpbi=NULL;
    delete[] buf;
    return FALSE;
    }catch (...)
    {
    #ifdef _DEBUG
    AfxMessageBox("Ado Error");
    #endif
    return FALSE;
    } int nLength=mfo.GetLength();
        char *buf2=new char[nLength];
    memmove(buf2,mfo.Detach(),nLength); char *pbuf=buf2; try
    {
    m_set->AddNew();
         m_set->PutCollect("KeyLogID",long(KeyId));
         m_set->PutCollect("Code2",_variant_t(m_mac));
    }catch(_com_error e)
    {
    CString error="保存GIF图片时出错,错误代码:";
    error+=e.ErrorMessage();
    error+="对该错误的说明:";
    _bstr_t err=e.Description();
    error+=(LPCTSTR)err;
    SaveLog(error.GetBuffer(0));
    return FALSE;
    GlobalUnlock(hDib);
    GlobalFree(hDib);  
          pbuf=NULL;
    lpbi=NULL;
    delete[] buf;
    }   VARIANT varBLOB;
        SAFEARRAY *psa;
        SAFEARRAYBOUND rgsabound[1];
    if(buf2)
    {    
    rgsabound[0].lLbound = 0;
    rgsabound[0].cElements = nLength;
    psa = SafeArrayCreate(VT_UI1, 1, rgsabound);///创建SAFEARRAY对象
    for (long i = 0; i < (long)nLength; i++)
    SafeArrayPutElement (psa, &i, buf2++);                         ///将pBuf指向的二进制数据保存到SAFEARRAY对象psa中
    varBLOB.vt = VT_ARRAY | VT_UI1; ///将varBLOB的类型设置为BYTE类型的数组
    varBLOB.parray = psa;   ///为varBLOB变量赋值
    try
    {
    m_set->GetFields()->GetItem("PicImage")->AppendChunk(varBLOB);///加入BLOB类型的数据
    }catch (_com_error e)
    {
    CString error="执行SQL命令出错,错误代码:";
         error+=e.ErrorMessage();
         error+="对该错误的说明:";
         _bstr_t err=e.Description();
         error+=(LPCTSTR)err;
         SaveLog(error.GetBuffer(0));
    GlobalUnlock(hDib);
    GlobalFree(hDib); 
    pbuf=NULL;
    lpbi=NULL;
    delete[] buf;
    delete[] buf2;
    return FALSE;
    }
    catch (...)
    {
    GlobalUnlock(hDib);
    GlobalFree(hDib);  
         pbuf=NULL;
    lpbi=NULL;
    delete[] buf;
    delete[] buf2;
    return FALSE;
    } }
    try
    {
    m_set->Update();
    }
    catch(_com_error e)
    {
    CString error="更新数据库时出错,错误代码:";
    error+=e.ErrorMessage();
    error+="对该错误的说明:";
    _bstr_t err=e.Description();
    error+=(LPCTSTR)err;
    SaveLog(error.GetBuffer(0));
    GlobalUnlock(hDib);
    GlobalFree(hDib);  
            lpbi=NULL;
    pbuf=NULL;
    delete[] buf;
    delete[] buf2;
    return FALSE;
    }
      GlobalUnlock(hDib);
        GlobalFree(hDib);  
    lpbi=NULL;
    pbuf=NULL;
        delete[] buf;
    delete[] buf2;
    SaveLog("保存图片成功");
    return TRUE;
    }
    这是上面贴剩的代码,全贴出来不允许说帖子太长了
      

  6.   

    你没有delete mon;
    你在最开始的时候new了:
    CMon *mon;
    mon=new CMon;
    所以应该delete