编写截屏工具遇到的问题
.386
.Model Flat, StdCall
Option Casemap :None
Include D:\masm32\include\windows.inc
Include D:\masm32\include\user32.inc
Include D:\masm32\include\kernel32.inc
Include D:\masm32\include\gdi32.inc
includelib D:\masm32\lib\gdi32.lib
IncludeLib D:\masm32\lib\user32.lib
IncludeLib D:\masm32\lib\kernel32.lib
.DATA
szClassName db "MASMPlus_Class",0
szChildClassName db "Class",0
hInstance dd ?;实例句柄
lpError dd ?;如果使用GetLastError函数话,使用这个变量做字符串指针
stRect RECT <>
hDCScreen dd ?;内存DC句柄
hBmpScreen dd ?;内存位图句柄
hChildWnd dd ?;子窗口句柄
point dd ?,?;鼠标指针位置
oldpoint dd ?,?;同上
.CODE
_ChildProc proc uses ebx esi edi hWnd,uMsg,wParam,lParam
local @hDC
local @stPs:PAINTSTRUCT
mov eax,uMsg
.if eax == WM_PAINT
invoke BeginPaint,hWnd,addr @stPs
mov @hDC,eax
invoke GetClientRect,hWnd,offset stRect
mov eax,oldpoint
mov ecx,oldpoint+4;取得子窗口原点相对父窗口原点的位移
invoke BitBlt,@hDC,0,0,stRect.right,stRect.bottom,\
hDCScreen,eax,ecx,NOTSRCCOPY
invoke EndPaint,hWnd,addr @stPs
.elseif eax == WM_SIZE
mov esi,lParam
test esi,esi
jz @ret
mov eax,point
mov ecx,point+4
mov edi,esi
and esi,0fffh
shr edi,16
cmp eax,esi;小的放eax做子窗口的原点
jb @f
je @ret
xchg eax,esi
@@:
sub esi,eax;得到x轴增量
cmp ecx,edi
jb @f
je @ret
xchg ecx,edi
@@:
sub edi,ecx;得到y轴增量
mov oldpoint,eax
mov oldpoint+4,ecx;临时原点坐标
invoke SetWindowPos,hWnd,HWND_TOPMOST,eax,ecx,esi,edi,SWP_SHOWWINDOW;设置窗口大小和位置
invoke InvalidateRect,hWnd,0,FALSE;刷新屏幕
.elseif eax == WM_CLOSE||eax == WM_KEYDOWN
invoke DestroyWindow,hWnd
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
@ret:
xor eax,eax
ret
_ChildProc endp
WndProc proc uses ebx esi edi hWnd:DWORD,uMsg:DWORD,wParam :DWORD,lParam :DWORD
local @stPs:PAINTSTRUCT
local @hDC
mov eax,uMsg
.if eax == WM_PAINT;拷贝临时内存DC到自己的DC
invoke BeginPaint,hWnd,addr @stPs
mov @hDC,eax
invoke GetClientRect,hWnd,offset stRect
invoke BitBlt,@hDC,0,0,stRect.right,stRect.bottom,hDCScreen,0,0,SRCCOPY
invoke EndPaint,hWnd,addr @stPs
.elseif eax == WM_CREATE
invoke GetDesktopWindow;得到桌面的窗口句柄
push eax
invoke GetClientRect,eax,offset stRect;获取它的客户区大小
mov eax,[esp]
invoke GetDC,eax;获取桌面DC
mov @hDC,eax
invoke CreateCompatibleDC,eax;创建内存DC
mov hDCScreen,eax
invoke CreateCompatibleBitmap,@hDC,stRect.right,stRect.bottom;创建内存位图
mov hBmpScreen,eax
invoke SelectObject,hDCScreen,hBmpScreen;装入位图
invoke BitBlt,hDCScreen,0,0,stRect.right,stRect.bottom,@hDC,0,0,NOTSRCCOPY
pop eax;从桌面DC拷贝到临时内存DC
invoke ReleaseDC,eax,@hDC
.elseif eax == WM_MOUSEMOVE
.if wParam == MK_LBUTTON
invoke SendMessage,hChildWnd,WM_SIZE,SIZE_RESTORED,lParam
.endif;在WM_MOUSEMOVE消息中改变子窗口大小
.elseif eax == WM_LBUTTONDOWN
.if hChildWnd != 0;如果已经创建,就先关闭它
invoke SendMessage,hChildWnd,WM_CLOSE,0,0
.endif
mov eax,lParam
mov ecx,eax
shr ecx,16
and eax,0ffffh
mov point,eax
mov point+4,ecx
mov oldpoint,eax
mov oldpoint+4,ecx;计算子窗口的显示位置
invoke CreateWindowEx,WS_EX_TOPMOST,offset szChildClassName,0,\
WS_POPUP or WS_CHILD or WS_THICKFRAME,\
eax,ecx,2,2,hWnd,NULL,hInstance,NULL
mov hChildWnd,eax
invoke ShowWindow,eax,SW_SHOWNORMAL;显示窗口
invoke UpdateWindow,hChildWnd
.elseif eax == WM_RBUTTONDOWN
invoke SendMessage,hChildWnd,WM_CLOSE,0,0;右键关闭子窗口
.elseif eax == WM_DESTROY||eax==WM_KEYDOWN
invoke SendMessage,hChildWnd,WM_CLOSE,0,0
invoke PostQuitMessage,NULL
invoke DeleteDC,hDCScreen
invoke DeleteObject,hBmpScreen
.else
invoke DefWindowProc,hWnd,eax,wParam,lParam
ret
.endif
xor eax,eax
ret
WndProc endp
WinMain proc
LOCAL @WC :WNDCLASSEX
LOCAL @Msg :MSG
local @hWnd :HWND
invoke RtlZeroMemory,addr @WC,sizeof @WC
mov @WC.cbSize,sizeof WNDCLASSEX
mov @WC.style,CS_HREDRAW or CS_VREDRAW
mov @WC.lpfnWndProc,offset WndProc
push hInstance
pop @WC.hInstance
mov @WC.lpszClassName,offset szClassName
invoke LoadCursor,0,IDC_ARROW
mov @WC.hCursor,eax
invoke RegisterClassEx, ADDR @WC
;父窗口的窗口类
mov @WC.lpszClassName,offset szChildClassName
mov @WC.lpfnWndProc,offset _ChildProc
invoke RegisterClassEx, ADDR @WC
;子窗口的窗口类
invoke CreateWindowEx,0,ADDR szClassName,0,WS_POPUPWINDOW,\
500,300,400,400,NULL,NULL,hInstance,NULL
;创建一个全屏无边框窗口
mov @hWnd,eax
invoke ShowWindow,@hWnd,SW_MAXIMIZE;最大化
invoke UpdateWindow,@hWnd
StartLoop:
invoke GetMessage,ADDR @Msg,NULL,0,0
or eax,eax
je ExitLoop
invoke DispatchMessage, ADDR @Msg
jmp StartLoop
ExitLoop:
mov eax,@Msg.wParam
ret
WinMain endp
START:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke WinMain
invoke ExitProcess,0
END START
错误表现为 我从某个点向右下截屏,却截到的点坐上的,令请指点WS_POPUPWINDOW风格的窗口如何在运行时设置大小。