小弟新手,前两天想要模仿一个windows自带的放大镜程序,不想遇到几个问题无法实现,特来向各位大大求救,望各位不吝赐教:
1。如何实现磁性窗口?使窗口在移动拖动过程中,靠近屏幕边缘就自动贴边。本来以为在WM_MOVING里面判断位置然后用MOVEWINDOW就可以实现,不过未能解决。猜想是MOVEWINDOW也会发送WM_MOVING消息吧?
2。如何限制桌面的图标排列在指定区域?就象windows自带的那个放大镜实现的功能一样。
附上源码,请高人批判指教:
.386
.model flat,stdcall
option casemap:none
include windows.inc
include kernel32.inc
include user32.inc
include gdi32.inc
includelib kernel32.lib
includelib user32.lib
includelib gdi32.lib
.data?
hMenu dd ? ;菜单句柄
hDesktop dd ? ;桌面句柄
ddMap dd ? ;倍数
ddWidth dd ? ;缩放区域宽度
ddHeight dd ? ;缩放区域高度
ddScreenX dd ? ;屏幕宽度
ddScreenY dd ? ;屏幕高度
szBuffer db 64 dup (?)
.data
szCaption db '当前缩放比例:%d倍',0
szClass db 'MyClass',0
szText db '单击拖动窗口',0
szMenu1 db '缩放比例(&F)',0
szMenu2 db '2倍 (&2)',0
szMenu3 db '3倍 (&3)',0
szMenu4 db '4倍 (&4)',0
szMenu5 db '退出放大镜(&x)',0
.code
_CreateMenu proc hWnd
LOCAL @hSubMenu
invoke CreateMenu
mov hMenu,eax
invoke CreatePopupMenu
mov @hSubMenu,eax
invoke AppendMenu,@hSubMenu,MF_STRING,2,offset szMenu2
invoke AppendMenu,@hSubMenu,MF_STRING,3,offset szMenu3
invoke AppendMenu,@hSubMenu,MF_STRING,4,offset szMenu4
invoke AppendMenu,@hSubMenu,MF_SEPARATOR,NULL,NULL
invoke AppendMenu,@hSubMenu,MF_STRING,5,offset szMenu5
invoke AppendMenu,hMenu,MF_POPUP,@hSubMenu,offset szMenu1
invoke SetMenu,hWnd,hMenu
invoke CheckMenuRadioItem,hMenu,2,4,ddMap,MF_BYCOMMAND
xor eax,eax
ret
_CreateMenu endp
_ProcTimer proc hWnd,uMsg,idEvent,dwTime
LOCAL @hdcWnd,@hdcDesktop
LOCAL @stRect:RECT
LOCAL @stPoint:POINT
pushad
invoke GetClientRect,hWnd,addr @stRect
invoke GetDC,hWnd
mov @hdcWnd,eax
invoke GetDC,hDesktop
mov @hdcDesktop,eax
invoke GetCursorPos,addr @stPoint
mov ecx,ddWidth
shr ecx,1
mov eax,@stPoint.x ;RectLeft=CurrentPosX-(WindowWidth÷2)
sub eax,ecx ;
jae @f ;if RectLeft < ScreenLeft then
xor eax,eax ;RectLeft = ScreenLeft = 0
@@: ;
mov ebx,eax ;RectLeft → ebx
add eax,ddWidth ;
sub eax,ddScreenX ;if RectRight > ScreenWidth then
jb @f ;RectLeft = ScreenRight - WindowWidth
sub ebx,eax ;
@@:
mov eax,ddHeight
shr eax,1
mov ecx,@stPoint.y ;RectTop=CurrentPosY-(WindowHeight÷2)
sub ecx,eax ;
jae @f ;if RectTop < ScreenTop then
xor ecx,ecx ;RectTop = ScreenTop = 0
@@: ;
mov edx,ecx ;RectTop → edx
add ecx,ddHeight ;
sub ecx,ddScreenY ;if RectBottom > ScreenBottom then
jb @f ;RectTop = ScreenBottom - WindowHeight
sub edx,ecx ;
@@: ;
invoke StretchBlt,@hdcWnd,0,0,@stRect.right,@stRect.bottom,@hdcDesktop,ebx,edx,ddWidth,ddHeight,SRCCOPY
invoke ReleaseDC,hWnd,@hdcWnd
invoke ReleaseDC,hDesktop,@hdcDesktop
popad
ret
_ProcTimer endp
_ProcMsg proc uses ebx edi esi hWnd,wMsg,wParam,lParam
; LOCAL @stPaint:PAINTSTRUCT
; LOCAL @stRect:RECT
; LOCAL @hdc
.if wMsg == WM_SIZE
;获得显示区域的长和宽
; invoke GetClientRect,hWnd,addr @stRect
; mov eax,@stRect.right
; xor edx,edx
; div ddMap
; mov ddWidth,eax
; xor edx,edx
; mov eax,@stRect.bottom
; div ddMap
; mov ddHeight,eax
;lParam高16位保存的是当前窗口高度,低16位保存的是当前窗口宽度
mov eax,lParam ;
movzx eax,ax ;
xor edx,edx ;RectWidth = WindowWidth ÷ 缩放比例
div ddMap ;
mov ddWidth,eax ;
mov eax,lParam ;
shr eax,16 ;
xor edx,edx ;RectHeight = WindowHeight ÷ 缩放比例
div ddMap ;
mov ddHeight,eax ;
.elseif wMsg == WM_COMMAND
mov eax,wParam
movzx eax,ax
mov ddMap,eax
cmp eax,5 ;如果选择了退出
jnz @f
invoke DestroyWindow,hWnd
xor eax,eax
ret
@@:
invoke CheckMenuRadioItem,hMenu,2,4,ddMap,MF_BYCOMMAND
invoke ShowWindow,hWnd,SW_MINIMIZE
invoke wsprintf,offset szBuffer,offset szCaption,ddMap
invoke SetWindowText,hWnd,offset szBuffer
invoke ShowWindow,hWnd,SW_RESTORE
; .elseif wMsg == WM_PAINT
; invoke BeginPaint,hWnd,addr @stPaint
; mov @hdc,eax
; invoke GetClientRect,hWnd,addr @stRect
; invoke DrawText,@hdc,offset szText,-1,addr @stRect,DT_CENTER or DT_SINGLELINE or DT_VCENTER
; invoke EndPaint,hWnd,addr @stPaint
.elseif wMsg == WM_LBUTTONDOWN
invoke SendMessage,hWnd,WM_NCLBUTTONDOWN,HTCAPTION,0
.elseif wMsg == WM_CREATE
invoke _CreateMenu,hWnd
invoke SetTimer,hWnd,100,100,offset _ProcTimer
invoke SetWindowPos,hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE or SWP_NOSIZE
.elseif wMsg == WM_DESTROY
invoke DestroyMenu,hMenu
invoke KillTimer,hWnd,100
invoke PostQuitMessage,0
.else
invoke DefWindowProc,hWnd,wMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
_ProcMsg endp
_Main proc
LOCAL @stMsg:MSG
LOCAL @stWndCls:WNDCLASSEX
;初始化
mov ddMap,2
invoke wsprintf,offset szBuffer,offset szCaption,ddMap
invoke GetDesktopWindow
mov hDesktop,eax
invoke RtlZeroMemory,addr @stWndCls,sizeof WNDCLASSEX + sizeof MSG
;填充并注册窗口类
invoke GetModuleHandle,NULL
mov @stWndCls.hInstance,eax
invoke LoadIcon,NULL,IDI_HAND
mov @stWndCls.hIcon,eax
invoke LoadCursor,NULL,IDC_CROSS
mov @stWndCls.hCursor,eax
mov @stWndCls.cbSize,sizeof WNDCLASSEX
mov @stWndCls.lpfnWndProc,offset _ProcMsg
mov @stWndCls.lpszClassName,offset szClass
mov @stWndCls.hbrBackground,COLOR_WINDOW + 1
invoke RegisterClassEx,addr @stWndCls
;窗口位置调整为水平居中,垂直居上
invoke GetSystemMetrics,SM_CXSCREEN
mov ddScreenX,eax
sub eax,600
shr eax,1
push eax
invoke GetSystemMetrics,SM_CYSCREEN
mov ddScreenY,eax
xor eax,eax
pop ecx
;创建窗口
invoke CreateWindowEx,NULL,offset szClass,offset szBuffer,\
WS_VISIBLE or WS_OVERLAPPEDWINDOW,ecx,eax,600,200,\
NULL,NULL,NULL,NULL
;消息循环
@@:
invoke GetMessage,addr @stMsg,NULL,NULL,NULL
test eax,eax
jz @f
invoke TranslateMessage,addr @stMsg
invoke DispatchMessage,addr @stMsg
jmp @b
@@:
xor eax,eax
ret
_Main endp
start:
jmp _Main
end start
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!