标题:现场直憋:从零开始学习 使用win32汇编写一个屏幕截图 截屏 小程序 长期更新 ...
只看楼主
信箱有效
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:蒙面侠
威 望:9
帖 子:1102
专家分:4268
注 册:2012-6-19
得分:0 
;因为是一点点的慢慢写,所以全局变量和局部变量没办法刚开始就都定义好,只能用
;的时候再定义,这个是获取屏幕上显示的内容子程序。

_GetDisPlayBmp proc uses ebx esi edi
    LOCAL @bmi:BITMAPINFO
    LOCAL @hDc
    LOCAL @MemDc
    invoke      RtlZeroMemory,addr @bmi,sizeof @bmi   
    mov         ebx,sizeof BITMAPINFO
    mov         @bmi.bmiHeader.biSize,ebx
    invoke      GetSystemMetrics,SM_CXSCREEN
    mov         @bmi.bmiHeader.biWidth,eax
    invoke      GetSystemMetrics,SM_CYSCREEN
    mov         @bmi.bmiHeader.biHeight,eax
    mov         @bmi.bmiHeader.biPlanes,1
    mov         @bmi.bmiHeader.biBitCount,24
以上是定义一个bitmapinfo结构,初始化其中的bitmapinfoheader结构的几个重要字段

    invoke      GetDC,NULL
    mov         @hDc,eax
    invoke      CreateCompatibleDC,@hDc
    mov         @MemDc,eax
获取屏幕DC,然后在内存中创建一个对应该设备环境的兼容DC名字为@MemDc
2012-10-14 12:09
信箱有效
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:蒙面侠
威 望:9
帖 子:1102
专家分:4268
注 册:2012-6-19
得分:0 
invoke     CreateDIBSection,@MemDc,addr @bmi,DIB_RGB_COLORS,addr @bmpData,NULL,0
   
mov        hBmp,eax
再定义一个@bmpData,MSDN上说:[out] Pointer to a variable that receives a pointer to the location of the DIB bit values.
createdibsection执行后,该变量里是个指针 指向DIB数据。

再定义个全局变量hBmp,它是一个位图句柄,指向刚刚由CreateDIBSection创建的与设备无关位图的句柄。而@bmpData则指向其中的位数据。


    invoke     SelectObject,@MemDc,hBmp
    invoke     BitBlt,@MemDc,   0,   0,   @bmi.bmiHeader.biWidth, @bmi.bmiHeader.               biHeight,@hDc,   0,   0,   SRCCOPY

    invoke     ReleaseDC,NULL,   @hDc
    invoke     DeleteDC,@MemDc  
    xor        eax,eax
               ret
_GetDisPlayBmp endp
CreateDIBSection创建的虽然是DIB块,但是是可以直接被操作的,选入@MemDc,将屏幕内容拷贝进去。  这个子程序最后的结果就是获得了一个和屏幕内容一样的位图句柄hBmp。

2012-10-14 13:08
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
得分:0 
信箱哥 你被位图Dog了。

梅尚程荀
马谭杨奚







                                                       
2012-10-14 14:43
有容就大
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:东土大唐
等 级:版主
威 望:74
帖 子:9048
专家分:14309
注 册:2011-11-11
得分:0 
是哦 这个应该给个颜色啊 怎么忘了 呵呵。。。

梅尚程荀
马谭杨奚







                                                       
2012-10-14 19:58
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
得分:0 
来学习了 搬砖真辛苦啊 没心情看了 纯支持了
2012-10-14 20:06
水哥
Rank: 5Rank: 5
等 级:贵宾
威 望:15
帖 子:65
专家分:111
注 册:2012-8-11
得分:0 
copy DC
2012-10-19 20:09
信箱有效
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:蒙面侠
威 望:9
帖 子:1102
专家分:4268
注 册:2012-6-19
得分:0 
以下是引用水哥在2012-10-19 20:09:22的发言:

copy DC
大家都知道是copy DC。
2012-10-20 02:38
Alar30
Rank: 10Rank: 10Rank: 10
等 级:贵宾
威 望:10
帖 子:988
专家分:1627
注 册:2009-9-8
得分:0 
现场版的啊
不错不错。。
2012-10-20 20:54
信箱有效
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:蒙面侠
威 望:9
帖 子:1102
专家分:4268
注 册:2012-6-19
得分:0 
本来还在想着怎么才能存成BMP文件呢。。。
MSDN真是个好东西,居然有C源码例子,学习一下,改成汇编。
程序代码:
int CaptureAnImage(HWND hWnd)
{
    HDC hdcScreen;
    HDC hdcWindow;
    HDC hdcMemDC = NULL;
    HBITMAP hbmScreen = NULL;
    BITMAP bmpScreen;

    // Retrieve the handle to a display device context for the client
    // area of the window.
    hdcScreen = GetDC(NULL);
    hdcWindow = GetDC(hWnd);

    // Create a compatible DC which is used in a BitBlt from the window DC
    hdcMemDC = CreateCompatibleDC(hdcWindow); 

    if(!hdcMemDC)
    {
        MessageBox(hWnd, L"CreateCompatibleDC has failed",L"Failed", MB_OK);
        goto done;
    }

    // Get the client area for size calculation
    RECT rcClient;
    GetClientRect(hWnd, &rcClient);

    //This is the best stretch mode
    SetStretchBltMode(hdcWindow,HALFTONE);

    //The source DC is the entire screen and the destination DC is the current window (HWND)
    if(!StretchBlt(hdcWindow,
               0,0,
               rcClient.right, rcClient.bottom,
               hdcScreen,
               0,0,
               GetSystemMetrics (SM_CXSCREEN),
               GetSystemMetrics (SM_CYSCREEN),
               SRCCOPY))
    {
        MessageBox(hWnd, L"StretchBlt has failed",L"Failed", MB_OK);
        goto done;
    }
   
    // Create a compatible bitmap from the Window DC
    hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top);
   
    if(!hbmScreen)
    {
        MessageBox(hWnd, L"CreateCompatibleBitmap Failed",L"Failed", MB_OK);
        goto done;
    }

    // Select the compatible bitmap into the compatible memory DC.
    SelectObject(hdcMemDC,hbmScreen);
   
    // Bit block transfer into our compatible memory DC.
    if(!BitBlt(hdcMemDC,
               0,0,
               rcClient.right-rcClient.left, rcClient.bottom-rcClient.top,
               hdcWindow,
               0,0,
               SRCCOPY))
    {
        MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK);
        goto done;
    }

    // Get the BITMAP from the HBITMAP
    GetObject(hbmScreen,sizeof(BITMAP),&bmpScreen);
    
    BITMAPFILEHEADER   bmfHeader;   
    BITMAPINFOHEADER   bi;
    
    bi.biSize = sizeof(BITMAPINFOHEADER);   
    bi.biWidth = bmpScreen.bmWidth;   
    bi.biHeight = bmpScreen.bmHeight; 
    bi.biPlanes = 1;   
    bi.biBitCount = 32;   
    bi.biCompression = BI_RGB;   
    bi.biSizeImage = 0; 
    bi.biXPelsPerMeter = 0;   
    bi.biYPelsPerMeter = 0;   
    bi.biClrUsed = 0;   
    bi.biClrImportant = 0;

    DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;

    // Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that
    // call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc
    // have greater overhead than HeapAlloc.
    HANDLE hDIB = GlobalAlloc(GHND,dwBmpSize);
    char *lpbitmap = (char *)GlobalLock(hDIB);    

    // Gets the "bits" from the bitmap and copies them into a buffer
    // which is pointed to by lpbitmap.
    GetDIBits(hdcWindow, hbmScreen, 0,
        (UINT)bmpScreen.bmHeight,
        lpbitmap,
        (BITMAPINFO *)&bi, DIB_RGB_COLORS);

    // A file is created, this is where we will save the screen capture.
    HANDLE hFile = CreateFile(L"captureqwsx.bmp",
        GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL, NULL);  
   
    // Add the size of the headers to the size of the bitmap to get the total file size
    DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    //Offset to where the actual bitmap bits start.
    bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
   
    //Size of the file
    bmfHeader.bfSize = dwSizeofDIB;
   
    //bfType must always be BM for Bitmaps
    bmfHeader.bfType = 0x4D42; //BM  

    DWORD dwBytesWritten = 0;
    WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
   
    //Unlock and Free the DIB from the heap
    GlobalUnlock(hDIB);   
    GlobalFree(hDIB);

    //Close the handle for the file that was created
    CloseHandle(hFile);
      
    //Clean up
done:
    DeleteObject(hbmScreen);
    DeleteObject(hdcMemDC);
    ReleaseDC(NULL,hdcScreen);
    ReleaseDC(hWnd,hdcWindow);

    return 0;
}


2012-10-21 23:24
无敌小默然
Rank: 1
等 级:新手上路
威 望:1
帖 子:8
专家分:5
注 册:2010-11-27
得分:0 
你喜欢。
2012-11-07 10:18



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-382877-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 1.316002 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved