| 网站首页 | 资讯 | Hack | 漏洞 | 网管 | 编程 | 培训 | 品黑页 | 软件 | 论坛 | 动画 | 视频 | 经典 | 教学站 | 黑客点睛 | 
服务导航 我要发布 主力频道 空间域名 精华收集 服务器出租 黑客培训 光盘刻录 特色服务 解决方案 我要投诉
您现在的位置: 华夏黑客同盟 >> 编程 >> 其它编程 >> 正文 用户登录 新用户注册
Win32汇编教程八           ★★★ 【字体:
Win32汇编教程八
作者:不详 文章来源:华盟收集 点击数: 更新时间:2007-7-9

有关GDI和位图
    GDI 即图形设备界面,是 Windows 最重要的部分之一,它大部分由 GDI32.DLL 库中的 API 来处理,GDI 的主要目的之一是支持与设备无关的图形编程,对于 Dos 下的图形编程,很多人可能“心有余悸”,因为PC 中有太多种类的显示卡,而几乎每个显示卡的处理都是不同的,即使后来有了 Vesa 编程,我们还是不能全部撇开具体的硬件,Windows GDI 使我们对图形的编程变得相对简单了很多,由于GDI 是 Windows 最庞大的部分,并不是几句话能讲清楚的,本节要讲的是 Windows 下GDI 的基本处理步骤和简单的位图处理,并没有涉及到 Directx 一类的编程。只希望能对朋友们有所启发。
    Windows 并不允许程序员访问显示硬件,它的所有对屏幕的操作是通过环境设备(DC)来处理的,屏幕上的每一个窗口对应一个DC,你可以把一个DC 想象成这个窗口的视频缓冲区,你对DC的操作结果会反映到屏幕上,在窗口的DC之外,你也可以自己建立DC,这相当于建立一个内存中的缓冲区,你对这个DC的操作结果保存在内存中。你也可以用 API 在不同的DC之间拷贝数据,比如说你可以在内存DC 中先建立好数据,然后拷贝到窗口的DC中,就相当于完成了屏幕的刷新。
    与DC的取得、建立取消有关的API有以下几种:

GetDC(hWnd) - 取得某个窗口的DC,API 返回对应的 DC 句柄
ReleaseDC(hWnd,hDC) - 释放用 GetDC 取得的 DC 句柄
CreateCompatibleDC(hDC) - 从一个已知的 DC 句柄中建立一个内存 DC,各种参数、属性参考已知的 DC
DeleteDC(hDC) - 删除用CreateCompatibleDC 建立的 DC
上面的4个API,必须成对出现,用 GetDC 取得的DC 必须用 ReleaseDC 释放,而用 CreateCompatibleDC 建立的 DC 必须用 DeleteDC 删除,不能混淆。DC 的作用范围:用 GetDC 取得的窗口 DC 必须尽快释放,你不应该在 Windows 的不同消息之间保存 DC 句柄,而用 CreateCompatibleDC 建立的 DC 可以长期保存,举例说明,如果你在 WM_PAINT 和 WM_SIZE 消息中都要对窗口的 DC 进行操作,你不能在 WM_INIT 时先 GetDC,然后保存句柄,最后在 WM_CLOSE 消息时 ReleaseDC,而是必须在 WM_PAINT 和 WM_SIZE 开始的地方 GetDC,在消息结束的地方就 ReleaseDC,而用 CreateCompatibleDC 建立的则相反,你可以在 WM_INIT 时建立,在 WM_CLOSE 时删除。
    如果想把一个位图画到 DC 中,你只需简单的用 invoke SelectObject,hDc,hBitmap 就行了,是不是很简单?但图形操作并不是单单把位图放入屏幕就行了,还要涉及到位的操作,如把前景位图的边缘去掉贴入背景位图等。 Windows 的 GDI 提供了下面一些 DC 间的拷贝 API,中间就包括了拷贝的模式:

BitBlt hDcDest,XDest,YDest,Width,Height,hDcSource,XSrc,YSrc,dwRop
这个 API 把 hDcSource 的 XSrc,YSrc 坐标处的内容拷贝到 hDcDest 的 XDest,YDest 处,拷贝大小为 Width,Height。
PatBlt hDc,X,Y,Width,Height,dwRop 是用预定义的刷子等 Object 填充 DC
StretchBlt,hDcDest,XDest,YDest,Width,Height,hDcSource,XSrc,YSrc,WidthSrc,HeightSrc,dwRop 是拷贝并自动缩放大小,你可以注意到它和 BitBlt 相比多了两个参数 WidthSrc 和 HeightSrc,别的都是一样的。
以上API 中的 dwRop 参数是最关键的,它的值有 SRCCOPY,SRCPAINT,SRCAND,DSTINVERT 等,表示源DC 拷贝到目标DC后象素的计算方法,SRCCOPY 表示用源DC覆盖目标DC,SRCPAINT是执行 OR 操作,SRCAND 是执行 AND 操作,DSTINVERT 是取反,举例说明,如果源DC中的某一点是黑色,目标DC对应的点是红色,那么用 SRCCOPY后,目标DC的点变成黑色,用SRCPAINT 后还是红色,因为黑 (000000) or 红(0000ff) =红(0000ff)。
     对应一般对屏幕或窗口进行图形操作的步骤如下。

用GetDC 取得目标窗口的 DC
用 CreateCompatibleDC 建立一个内存中的 DC用作缓冲区
用 SelectObject 填充内存DC 或别的办法对内存DC进行操作,一句话,先把要显示的东西处理好
用 BitBlt 把内存DC 拷贝到窗口 DC中,完成屏幕刷新。
本节的例子程序是一个屏幕放大镜,它把鼠标移动到的地方的屏幕内容放大一倍显示到自己的窗口中。

源程序 - 汇编源文件

以下是代码片段:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Programmed by 罗云彬, bigluo@telekbird.com.cn
; Website: http://asm.yeah.net
; LuoYunBin's Win32 ASM page (罗云彬的编程乐园)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 版本信息
; 汇编教程附带源程序 - 屏幕放大器
;    V1.0 ------ 2000年7月1日
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  .386
  .model flat, stdcall
  option casemap :none   ; case sensitive

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

include  windows.inc
include  user32.inc
include  kernel32.inc
include  comctl32.inc
include  comdlg32.inc
include  gdi32.inc

includelib user32.lib
includelib kernel32.lib
includelib comctl32.lib
includelib comdlg32.lib
includelib gdi32.lib

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

DLG_MAIN equ  1000
ID_BITMAP equ  1001

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  .data?

hWinPic  dd ?
hDcMem  dd ?
hBitmap  dd ?
hWinDesktop dd ?
hInstance dd ?
szBuffer db 256 dup (?)

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 子程序声明
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain PROTO :DWORD,:DWORD,:DWORD,:DWORD

  .data

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  .code

include  Win.asm

;********************************************************************
_ProcDlgMain proc uses ebx edi esi, \
  hWnd:DWORD,wMsg:DWORD,wParam:DWORD,lParam:DWORD
  local @stPoint:POINT
  local @hDcDesktop,@hDcPic

  mov eax,wMsg
  .if eax == WM_CLOSE
   invoke EndDialog,hWnd,NULL
   invoke KillTimer,hWnd,1
   invoke DeleteDC,hDcMem
   invoke DeleteObject,hBitmap
; *******************************************************************
  .elseif eax == WM_INITDIALOG
   invoke GetDlgItem,hWnd,ID_BITMAP
   mov hWinPic,eax
   invoke GetDesktopWindow
   mov hWinDesktop,eax
   invoke SetWindowPos,hWnd,HWND_TOPMOST,0,0,0,0,\
    SWP_NOMOVE or SWP_NOSIZE
; *******************************************************************
   invoke GetDC,hWinDesktop
   mov @hDcDesktop,eax
   invoke CreateCompatibleDC,@hDcDesktop
   mov hDcMem,eax
   invoke CreateCompatibleBitmap,@hDcDesktop,80,80
   mov hBitmap,eax
   invoke SelectObject,hDcMem,hBitmap
   invoke ReleaseDC,hWinDesktop,@hDcDesktop
   invoke SetTimer,hWnd,1,100,NULL
; *******************************************************************
  .elseif eax == WM_TIMER
   invoke GetCursorPos,addr @stPoint
   sub @stPoint.x,20
   sub @stPoint.y,20
   .if @stPoint.x < 0
    mov @stPoint.x,0
   .endif
   .if @stPoint.y < 0
    mov @stPoint.y,0
   .endif
   invoke GetDC,hWinDesktop
   mov @hDcDesktop,eax
   invoke GetDC,hWinPic
   mov @hDcPic,eax
   invoke PatBlt,hDcMem,0,0,80,80,BLACKNESS
   invoke StretchBlt,hDcMem,0,0,80,80,\
    @hDcDesktop,@stPoint.x,@stPoint.y,40,40,SRCCOPY
   invoke BitBlt,@hDcPic,0,0,80,80,\
    hDcMem,0,0,SRCCOPY
   invoke ReleaseDC,hWinDesktop,@hDcDesktop
   invoke ReleaseDC,hWinPic,@hDcPic
  .else
;********************************************************************
; 注意:对话框的消息处理后,要返回 TRUE,对没有处理的消息
; 要返回 FALSE
;********************************************************************
   mov eax,FALSE
   ret
  .endif    
  mov eax,TRUE
  ret
  
_ProcDlgMain endp
;********************************************************************
start:
  invoke GetModuleHandle,NULL
  mov hInstance,eax
  invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,0
  invoke ExitProcess,NULL

  end start

程序的分析和要点

    在程序的初始化中,我们用GetDc 取的桌面的屏幕的 DC,再用 CreateCompatibleDC 建立一个内存DC做缓冲区,建立一个位图再用 SelectObject 把 hDcMem 设置为这个位图是为了是 hDcMem 的大小变为 80x80。

   invoke GetDC,hWinDesktop
   mov @hDcDesktop,eax
   invoke CreateCompatibleDC,@hDcDesktop
   mov hDcMem,eax
   invoke CreateCompatibleBitmap,@hDcDesktop,80,80
   mov hBitmap,eax
   invoke SelectObject,hDcMem,hBitmap
   invoke ReleaseDC,hWinDesktop,@hDcDesktop
然后在程序的每 0.1 秒一次的 WM_TIMER 定时器消息中,我们先用 GetDC 取得桌面和对话框中文本框的句柄,然后用 PatBlt 把内存DC清除为黑色,再用 StretchBlt 从桌面DC中拷贝 40x40的区域到内存 DC 中,新的大小是 80x80(放大功能就是这样实现的),拷贝的位置是用 GetCursorPos 取得的,也就是鼠标的当前位置,最后用 BitBlt 把内存DC 拷贝到对话框中。如果直接把桌面DC 拷贝到对话框中也可以,但是当鼠标移动到屏幕边缘上时,由于屏幕外的点是无效的,所以对话框中的一部分会花屏,大家可以改动程序试试。

   invoke GetCursorPos,addr @stPoint
   invoke GetDC,hWinDesktop
   mov @hDcDesktop,eax
   invoke GetDC,hWinPic
   mov @hDcPic,eax
   invoke PatBlt,hDcMem,0,0,80,80,BLACKNESS
   invoke StretchBlt,hDcMem,0,0,80,80,\
    @hDcDesktop,@stPoint.x,@stPoint.y,40,40,SRCCOPY
   invoke BitBlt,@hDcPic,0,0,80,80,\
    hDcMem,0,0,SRCCOPY
   invoke ReleaseDC,hWinDesktop,@hDcDesktop
   invoke ReleaseDC,hWinPic,@hDcPic

责任编辑:郭瑞  联系方式  Email:郭瑞
电话:51228163
  • 上一篇编程:

  • 下一篇编程:
  • (只显示最新5条。评论内容只代表网友观点,与本站立场无关!)
    姓 名:
    * 游客填写  ·注册用户
    主 页:
    评 分:
    1分 2分 3分 4分 5分
    评论内容:
    验证码: *
  • 请遵守《互联网电子公告服务管理规定》及中华人民共和国其他各项有关法律法规。
  • 严禁发表危害国家安全、损害国家利益、破坏民族团结、破坏国家宗教政策、破坏社会稳定、侮辱、诽谤、教唆、淫秽等内容的评论 。
  • 用户需对自己在使用本站服务过程中的行为承担法律责任(直接或间接导致的)。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表网友个人观点,与本网站立场无关。
  • 最新hack更新
    最新推荐资讯
    相关编程
    学习汇编基础入门知识
    学习汇编基础入门知识
    学习汇编基础入门知识
    修改特征码掌握的知识
    Win32平台下Rootkit习作
    汇编ring3实现HOOKAPI
    汇编创建简单的窗口
    学习汇编基础入门知识
    MD5算法汇编代码[着重优化]
    安全探讨之用Win32汇编写双进程守
    最新会员软件
    最新推荐视频
    最新推荐动画

    Copyright @ 2005 77169.Net Inc. All rights reserved. 华夏黑客同盟 版权所有
    北京市电信通提供网络带宽

    mailto:webmaster@77169.net
    咨询QQ号:836982 / 59280880
    联系站长 QQ38588913
    热线电话: 86-10-67634029/676229433
    京ICP证041431号