用MASM32编程截取屏幕

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; 功能: 把屏幕内容拷贝到剪贴板并显示在程序窗口上
; 作者: Purple Endurer
;  环境: Windows 2000 PRO + MASM32 V8
;
; 日志
; ---------------------
; 2005.12.24 创建!
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.386
.model flat, stdcall
option casemap:none
include /masm32/include/windows.inc
include /masm32/include/gdi32.inc
include /masm32/include/kernel32.inc
include /masm32/include/user32.inc

includelib /masm32/lib/gdi32.lib
includelib /masm32/lib/kernel32.lib
includelib /masm32/lib/user32.lib

DlgProc PROTO :DWORD, :DWORD, :DWORD, :DWORD
CopyScreenToBitmap PROTO :DWORD
CopyBMPtoClipboard PROTO :HANDLE, :HWND
DrawBMP PROTO :HWND, :HANDLE

m_m2m MACRO d1, d2
    push d2
    pop d1
ENDM

IDD_dlgCopyScr  equ 8000
IDC_btnCopyScr  equ 1008


.data?
g_hInstance HINSTANCE ?
g_ScrRect   RECT    <>

.code
start:
    invoke GetModuleHandle, NULL
    mov    g_hInstance, eax

    ;m_m2m g_ScrRect.top, 0
    ;m_m2m g_ScrRect.left, 0
    ;m_m2m g_ScrRect.bottom, 200
    ;m_m2m g_ScrRect.right, 100

    invoke DialogBoxParam, g_hInstance, IDD_dlgCopyScr, NULL, OFFSET DlgProc,  NULL
    invoke ExitProcess, eax

DlgProc proc hWnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM
    .IF uMsg == WM_CLOSE
        invoke EndDialog, hWnd, NULL

 ;.ELSEIF uMsg == WM_INITDIALOG

    .ELSEIF (uMsg == WM_COMMAND)
        mov eax, wParam
        mov edx, eax
        shr edx, 16
        .if (dx == BN_CLICKED)              ;If button is clicked
            .IF (eax ==  IDC_btnCopyScr)
                invoke GetDesktopWindow
                invoke GetWindowRect, eax, ADDR g_ScrRect
                invoke CopyScreenToBitmap, ADDR g_ScrRect
                push eax
                invoke CopyBMPtoClipboard, eax, hWnd
                pop eax
                invoke DrawBMP, hWnd, eax
            .ENDIF
        .endif

    .ELSE
        mov eax, FALSE
        ret
    .ENDIF

    mov eax, TRUE
    ret
DlgProc endp

; lpRect 为指向要拷贝的屏幕区域的坐标结构的指针
CopyScreenToBitmap proc lpRect: DWORD
    LOCAL hScrDC, hMemDC: HDC       ;屏幕和内存设备描述表
    LOCAL hBitmap, hOldBitmap: HBITMAP    ;位图句柄
    LOCAL nX, nY, nX2, nY2: DWORD         ;选定区域坐标
    LOCAL nWidth, nHeight: DWORD          ;位图宽度和高度
    LOCAL xScrn, yScrn: DWORD             ;屏幕分辨率

    ;判断选定区域是否为空矩形
    invoke  IsRectEmpty, lpRect
    or eax, eax
    jz @F
    ;m_m2m eax, 1    ;是空矩形
    ret
@@:   
    ;为屏幕创建设备描述表
    xor eax, eax
    jz @F
    szDisplay db "DISPLAY", 0
@@:   
    invoke CreateDC, ADDR szDisplay, NULL, NULL, NULL
    cmp eax, NULL
    jne @F
    ;m_m2m eax, 2    ;不能创建DC
    ret
@@:   
    mov hScrDC, eax

   ;为屏幕设备描述表创建兼容的内存设备描述表
    invoke CreateCompatibleDC, hScrDC
    cmp eax, NULL
    jne @F
    ;m_m2m eax, 3    ;不能创建兼容的内存设备描述表
    ret
@@:   
    mov hMemDC, eax

    ;获得选定区域坐标
    mov eax, lpRect
    assume eax: ptr RECT
    m_m2m nX, [eax].left
    m_m2m nY, [eax].top
    m_m2m nX2, [eax].right
    m_m2m nY2, [eax].bottom
    assume eax: nothing

    ;获得屏幕分辨率
    invoke GetDeviceCaps, hScrDC, HORZRES
    mov xScrn, eax
    invoke GetDeviceCaps, hScrDC, VERTRES
    mov yScrn, eax

    ;确保选定区域是可见的
    .if (nX < 0)
        m_m2m nX, 0
    .endif

    .if (nY < 0)
        m_m2m nY, 0
    .endif

    mov eax, nX2
    .if (eax > xScrn)
        m_m2m nX2, xScrn
    .endif

    mov eax, nY2
    .if (eax > yScrn)
        m_m2m nY2, yScrn
    .endif

    mov eax, nX2
    sub eax, nX
    mov  nWidth, eax
   
    mov eax, nY2
    sub eax, nY
    mov nHeight, eax

    ;创建一个与屏幕设备描述表兼容的位图
    invoke CreateCompatibleBitmap, hScrDC, nWidth, nHeight
    cmp eax, NULL
    jne @F
    ;m_m2m eax, 4    ;不能创建屏幕设备描述表兼容的位图
    ret
@@:   
    mov hBitmap, eax

   ;把新位图选到内存设备描述表中
    invoke SelectObject, hMemDC, hBitmap
    cmp eax, NULL
    jne @F
    ;m_m2m eax, 5    ;an error occurs and the selected object is not a region
    ret
@@:   
    cmp eax, GDI_ERROR
    jne @F
    ;m_m2m eax, 6
    ret
@@:   
    mov hOldBitmap, eax

    ;把屏幕设备描述表拷贝到内存设备描述表中
    invoke BitBlt, hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY

    ;得到屏幕位图的句柄
    invoke SelectObject, hMemDC, hOldBitmap
    push eax    ;mov hBitmap, eax
   ;清除
    invoke DeleteDC, hScrDC
    invoke DeleteDC, hMemDC

    ;返回位图句柄
    pop eax     ;mov eax, hBitmap

    ret
CopyScreenToBitmap endp


;得到屏幕位图句柄以后,我们可以把屏幕内容粘贴到剪贴板上
;hBitmap: 位图句柄
;hWnd: 程序窗口句柄
CopyBMPtoClipboard proc hBitmap: HANDLE, hWnd: HWND
    invoke OpenClipboard, hWnd  ;
    or eax, eax
    jnz @F
    m_m2m eax, 1
    ret
@@:
    ;清空剪贴板
    invoke EmptyClipboard
    or eax, eax
    jnz @F
    m_m2m eax, 2
    ret
@@:
    ;把位图内容粘贴到剪贴板上
    invoke SetClipboardData, CF_BITMAP, hBitmap
    or eax, eax
    jnz @F
    m_m2m eax, 3
    ret
@@:
    ;关闭剪贴板
    invoke CloseClipboard
    or eax, eax
    jnz @F
    m_m2m eax, 4
    ret
@@:
    xor eax, eax
    ret
CopyBMPtoClipboard endp

;在指定窗口上绘制位图
DrawBMP proc hWnd: HWND, hBmp: HANDLE
    LOCAL hDC: HDC
    LOCAL hOld: DWORD
    LOCAL memDC :DWORD

    invoke GetDC, hWnd
    mov hDC, eax
    invoke CreateCompatibleDC, eax
    mov memDC, eax
   
    invoke SelectObject, memDC, hBmp
    mov hOld, eax

    invoke BitBlt, hDC, 120, 0, 1000, 1000, memDC, 0, 0, SRCCOPY

    invoke SelectObject, hDC, hOld
    invoke DeleteDC, memDC
    invoke DeleteDC, hDC
    ;xor eax, eax
    ret
DrawBMP endp

end start

;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;资源文件rsrc.rc
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#include "/masm32/include/resource.h"

#define IDD_dlgcopyScr              8000
#define IDC_btnCopyScr              1008


IDD_dlgcopyScr DIALOG 20, 20, 295, 165
STYLE 0x0004 | DS_CENTER | WS_CAPTION | DS_SYSMODAL | WS_SYSMENU | WS_MINIMIZEBOX
      | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
CAPTION "拷贝屏幕"
{
  PUSHBUTTON      "&C 拷贝屏幕", IDC_btnCopyScr, 5, 5, 52, 52, WS_BORDER
}

阅读更多

屏幕截取编程的问题

07-01

我用下面的代码实现屏幕截取编程,屏幕截取后写入到WORD中。由于向WORD中写入大量数据,当程序运行时,如果用户不离开程序界面,那么是没有问题的。可当用户点了别的程序的窗口后,比如显示桌面,那么程序运行屏幕截取的是桌面的屏幕,而不是我运行的程序的屏幕。怎么解决该问题?实现我运行的程序的屏幕截取,而不是当前屏幕。谢谢!分数有限,不好意思。rn---- 下面用vc来逐步介绍在windows95下的实现过程.首先我们要确定屏幕截取的区域,用lprect结构来定义.可以截取一个窗口,或整个屏幕.以下代码把选定的屏幕区域拷贝到位图中. rnrnhbitmap copyscreentobitmap(lprect lprect) rn//lprect 代表选定区域 rn rnhdc hscrdc, hmemdc; rn// 屏幕和内存设备描述表 rnhbitmap hbitmap, holdbitmap; rn// 位图句柄 rnint nx, ny, nx2, ny2; rn// 选定区域坐标 rnint nwidth, nheight; rn// 位图宽度和高度 rnint xscrn, yscrn; rn// 屏幕 rn分辨率 rnrn// 确保选定区域不为空矩形 rnif (isrectempty(lprect)) rnreturn null; rn//为屏幕创建设备描述表 rnhscrdc = createdc("display", null, null, null); rn//为屏幕设备描述表创建兼容的内存设备描述表 rnhmemdc = createcompatibledc(hscrdc); rn// 获得选定区域坐标 rnnx = lprect- >left; rnny = lprect- >top; rnnx2 = lprect- >right; rnny2 = lprect- >bottom; rn// 获得屏幕分辨率 rnxscrn = getdevicecaps(hscrdc, horzres); rnyscrn = getdevicecaps(hscrdc, vertres); rn//确保选定区域是可见的 rnif (nx 〈0) rnnx = 0; rnif (ny 〈 0) rnny = 0; rnif (nx2 > xscrn) rnnx2 = xscrn; rnif (ny2 > yscrn) rnny2 = yscrn; rnnwidth = nx2 - nx; rnnheight = ny2 - ny; rn// 创建一个与屏幕设备描述表兼容的位图 rnhbitmap = createcompatiblebitmap rn(hscrdc, nwidth, nheight); rn// 把新位图选到内存设备描述表中 rnholdbitmap = selectobject(hmemdc, hbitmap); rn// 把屏幕设备描述表拷贝到内存设备描述表中 rnbitblt(hmemdc, 0, 0, nwidth, nheight, rnhscrdc, nx, ny, srccopy); rn//得到屏幕位图的句柄 rnhbitmap = selectobject(hmemdc, holdbitmap); rn//清除 rndeletedc(hscrdc); rndeletedc(hmemdc); rn// 返回位图句柄 rnreturn hbitmap; rn rn

没有更多推荐了,返回首页