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

概述
    在前面八篇的 Win32asm 教程中,已经初步讲述了消息框、对话框、菜单、资源、GDI 等内容,基本上已经设计到了 Windows 界面的大部分内容,在继续新的 Windows 其他部分的内容如多线程、文件操作、内存操作之前,我先综合前面的内容并加上一些新内容,写上一篇综合篇。
本篇的例子程序是一个复杂形状的窗口,窗口的形状是根据位图自动计算得到的,这也就是在我编写的小闹钟中使用的技术(大家可以到我的软件发布中下载一个看看),由于以前在网上看到的有关特殊形状窗口的例子最多就是画一个圆形,或者几个方块和椭圆结合的形状,没有一篇文章指出如何画出如“唐老鸭”这样一个造型的窗口。本文使用的算法可以自动根据位图的形状计算窗口形状。
在源程序中,很多代码都是前面教程提到的,主要有以下部分:

首先建立一个标准的窗口。(参考窗口一节)
设置窗口为特殊形状。(见下面的程序分析)
在窗口的 WM_PAINT 消息中更新窗口的图片。(参考图形界面一节)
由于窗口没有标题栏,所以在右击窗口时弹出一个菜单。(参考菜单一节)
菜单中有个“关于本程序”项,里面有超联结文本。(参考窗口子类化一节)
Windows 里有专门的 API 来实现特殊形状的窗口,步骤是首先建立区域(Region),Region 可以合并,这样一来就可以用几个简单的区域合并出一个复杂的区域,建立、合并区域和设置窗口的 API 主要有以下几条:

CreateRectRgn(Left,Top,Right,Bottom) - 建立矩型区域
CreateEllipticRgn(Left,Top,Right,Bottom) - 建立椭圆区域
CreatePolygonRgn(lpPoints,NumberOfPoints,Mode) - 建立多边形区域,这些API返回区域句柄
CombineRgn(hDest,hSource1,hSource2,CombineMode) - 合并区域
SetWindowRgn(hWnd,hRgn,bRedraw) - 根据区域设置窗口形状
本程序的方法是扫描位图的点,按行设置区域,然后合并到总的区域中。

源程序 - 汇编源文件

以下是代码片段:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 是否包括调试代码
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DEBUG  = 0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Programmed by 罗云彬, bigluo@telekbird.com.cn
; Website: http://asm.yeah.net
; LuoYunBin's Win32 ASM page (罗云彬的编程乐园)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 版本信息
; 特殊形状窗口的演示程序 Ver 1.0
; 可以根据位图自动设置窗口的形状。
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

 .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  shell32.inc
 include  gdi32.inc

 includelib user32.lib
 includelib kernel32.lib
 includelib comctl32.lib
 includelib comdlg32.lib
 includelib shell32.lib
 includelib gdi32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;************** Equ 数据 **********************************
IDI_MAIN equ  1  ;icon
IDC_HANDLE equ  2  ;Cursor
;************** Equ 数据 **********************************
DLG_ABOUT equ  1200  ;dialog - about
ID_ABOUT_OK equ  1201
ID_EMAIL equ  1202
ID_HOMEPAGE equ  1203
;************** Equ 数据 **********************************
IDM_MAIN equ  2000
IDM_ABOUT equ  2001
IDM_EXIT equ  2002
;************** Equ 数据 **********************************
IDB_0  equ   3000  ;bitmap

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  .data?
hInstance dd  ?
hWinMain dd  ?
hIcon  dd  ?
hCursor  dd  ?
hMenu  dd  ?

hBmpBack dd  ? ;background bitmap
hDcBack  dd  ?

;************** 数据段 ************************************
  .data

szClassName db 'ShapeWindow',0

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

  .code

if  DEBUG
  include  Debug.asm
endif
;********************************************************************
; 设置窗口形状为BMP图形形状
; 参数:窗口句柄,BMP图形句柄
; 输入BMP图形要求:0,0处颜色为背景色
;********************************************************************
_SetWindowShape proc hWnd:DWORD,hBitMap:DWORD
  local @hDC:DWORD,@hBmpDC:DWORD
  local @stPs:PAINTSTRUCT
  local @stRect:RECT
  local @stBmp:BITMAP
  local @dwX:DWORD,@dwY:DWORD,@dwStartX:DWORD
  local @hRgn:DWORD,@hRgnTemp:DWORD
  local @rgbBack:DWORD

  invoke GetObject,hBitMap,sizeof BITMAP,addr @stBmp
  invoke GetWindowRect,hWnd,addr @stRect
  invoke ShowWindow,hWnd,SW_HIDE
  invoke MoveWindow,hWnd,@stRect.left,@stRect.top,\
   @stBmp.bmWidth,@stBmp.bmHeight,FALSE

  invoke  GetDC,hWnd
  mov @hDC,eax
  invoke CreateCompatibleDC,@hDC
  mov @hBmpDC,eax
  invoke SelectObject,@hBmpDC,hBitMap
;*************** 计算窗口形状 ***************************************
  invoke GetPixel,@hBmpDC,0,0
  mov @rgbBack,eax
  invoke CreateRectRgn,0,0,0,0
  mov @hRgn,eax

  mov @dwY,0
 .while TRUE
  mov @dwX,0
  mov @dwStartX,-1
    .while TRUE
  invoke GetPixel,@hBmpDC,@dwX,@dwY
  .if @dwStartX == -1
     .if eax != @rgbBack
   mov eax,@dwX
   mov @dwStartX,eax
     .endif
  .else
     .if eax == @rgbBack
   mov ecx,@dwY
   inc ecx
   invoke CreateRectRgn,@dwStartX,@dwY,@dwX,ecx
   invoke CombineRgn,@hRgn,@hRgn,eax,RGN_OR
   mov @dwStartX,-1
     .else
   mov eax,@dwX
   .if eax == @stBmp.bmWidth
    inc eax
    mov ecx,@dwY
    inc ecx
    invoke CreateRectRgn,@dwStartX,@dwY,eax,ecx
    invoke CombineRgn,@hRgn,@hRgn,eax,RGN_OR
    mov @dwStartX,-1
   .endif
     .endif
  .endif
  inc @dwX
  mov eax,@dwX
  .break .if eax > @stBmp.bmWidth
    .endw
  inc @dwY
  mov eax,@dwY
  .break .if eax > @stBmp.bmHeight
 .endw

  invoke SetWindowRgn,hWnd,@hRgn,TRUE
;********************************************************************
  invoke BitBlt,@hDC,0,0,@stBmp.bmWidth,@stBmp.bmHeight,\
   @hBmpDC,0,0,SRCCOPY
  invoke DeleteDC,@hBmpDC
  invoke ReleaseDC,hWnd,@hDC
  invoke InvalidateRect,hWnd,NULL,-1

  ret

_SetWindowShape endp
;********************************************************************
; 将窗口移动到屏幕中间
; 参数:窗口句柄
;********************************************************************
_CenterWindow proc hWnd:DWORD
  local @stRectDeskTop:RECT,@stRectWin:RECT
  local @dwWidth:DWORD,@dwHeight:DWORD

  invoke GetWindowRect,hWnd,addr @stRectWin
  invoke GetDesktopWindow
  mov ebx,eax
  invoke GetWindowRect,ebx,addr @stRectDeskTop

  mov eax,@stRectWin.bottom
  sub eax,@stRectWin.top
  mov @dwHeight,eax
  mov eax,@stRectWin.right
  sub eax,@stRectWin.left
  mov @dwWidth,eax

  mov ebx,@stRectDeskTop.bottom
  sub ebx,@dwHeight
  shr ebx,1
  mov ecx,@stRectDeskTop.right
  sub ecx,@dwWidth
  shr ecx,1

  invoke MoveWindow,hWnd,ecx,ebx,@dwWidth,@dwHeight,FALSE
  ret

_CenterWindow endp
;********************************************************************
include  About.asm

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 程序开始
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
  call _WinMain
  invoke ExitProcess,NULL

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 主窗口程序
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WinMain proc
  local @stWcMain:WNDCLASSEX
  local @stMsg:MSG

  invoke InitCommonControls
  invoke GetModuleHandle,NULL
  mov hInstance,eax
  invoke LoadIcon,hInstance,IDI_MAIN
  mov hIcon,eax
  invoke LoadMenu,hInstance,IDM_MAIN
  invoke GetSubMenu,eax,0 ;PopUp 菜单要用到子菜单
  mov hMenu,eax
;*************** 注册窗口类 *****************************************
  invoke LoadCursor,0,IDC_ARROW
  mov @stWcMain.hCursor,eax
  mov @stWcMain.cbSize,sizeof WNDCLASSEX
  mov @stWcMain.hIconSm,0
  mov @stWcMain.style,CS_HREDRAW or CS_VREDRAW
  mov @stWcMain.lpfnWndProc,offset WndMainProc
  mov @stWcMain.cbClsExtra,0
  mov @stWcMain.cbWndExtra,0
  mov eax,hInstance
  mov @stWcMain.hInstance,eax
  mov @stWcMain.hIcon,0
  mov @stWcMain.hbrBackground,COLOR_WINDOW + 1
  mov @stWcMain.lpszClassName,offset szClassName
  mov @stWcMain.lpszMenuName,0
  invoke RegisterClassEx,addr @stWcMain
;***************** 建立输出窗口 *****************************************
; 属性:没有标题栏,不显示在任务栏
;********************************************************************
  invoke CreateWindowEx,WS_EX_TOOLWINDOW,\
   offset szClassName,NULL,\
   WS_POPUP or WS_SYSMENU,\
   0,0,1,1,\
   NULL,NULL,hInstance,NULL

  invoke ShowWindow,hWinMain,SW_SHOWNORMAL
  invoke UpdateWindow,hWinMain
;*************** 消息循环 *******************************************
  .while TRUE
   invoke GetMessage,addr @stMsg,NULL,0,0
   .break .if eax == 0
   invoke TranslateMessage,addr @stMsg
   invoke DispatchMessage,addr @stMsg
  .endw
  ret

_WinMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
WndMainProc proc uses ebx edi esi, \
  hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
  local @stPos:POINT
  local @stPs:PAINTSTRUCT,@hDC:DWORD

  mov eax,uMsg
  .if eax == WM_CREATE
   mov eax,hWnd
   mov hWinMain,eax
   call _Init
;********************************************************************
  .elseif eax == WM_PAINT
   invoke BeginPaint,hWnd,addr @stPs
   mov @hDC,eax

   mov eax,@stPs.rcPaint.right
   sub eax,@stPs.rcPaint.left
   mov ecx,@stPs.rcPaint.bottom
   sub ecx,@stPs.rcPaint.top

   invoke BitBlt,@hDC,@stPs.rcPaint.left,@stPs.rcPaint.top,eax,ecx,\
    hDcBack,@stPs.rcPaint.left,@stPs.rcPaint.top,SRCCOPY

   invoke EndPaint,hWnd,addr @stPs
;********************************************************************
; 由于没有菜单,下面代码用于按下右键时弹出POPUP菜单
;********************************************************************
  .elseif eax == WM_RBUTTONDOWN
     .if wParam == MK_RBUTTON
   invoke GetCursorPos,addr @stPos
   invoke TrackPopupMenu,hMenu,TPM_LEFTALIGN,@stPos.x,@stPos.y,NULL,hWnd,NULL
     .endif
;********************************************************************
; 由于没有标题栏,下面代码用于按下左键时移动窗口
;********************************************************************
  .elseif eax == WM_LBUTTONDOWN
   invoke UpdateWindow,hWnd  ;即时刷新
   invoke ReleaseCapture
   invoke SendMessage,hWnd,WM_NCLBUTTONDOWN,HTCAPTION,0
;********************************************************************
  .elseif eax == WM_COMMAND
     .if lParam == 0
   mov eax,wParam
   .if ax == IDM_EXIT
    call _Quit
   .elseif ax == IDM_ABOUT
    invoke DialogBoxParam,hInstance,DLG_ABOUT,hWnd,offset AboutDialogProc,DLG_ABOUT
   .endif
     .endif
;********************************************************************
  .elseif eax == WM_CLOSE
   call _Quit
;********************************************************************
  .else
   invoke DefWindowProc,hWnd,uMsg,wParam,lParam
   ret
  .endif
;********************************************************************
; 注意:WndProc 处理 Windows 消息后,必须在 Eax 中返回 0
; 但是由 DefWindowProc 处理后的返回值不能改变,否则窗口
; 将无法显示!
;********************************************************************
  xor eax,eax
  ret

WndMainProc endp


;********************************************************************
_Init  proc
  local @hDC

  invoke SendMessage,hWinMain,WM_SETTEXT,0,offset szClassName
  invoke SendMessage,hWinMain,WM_SETICON,ICON_SMALL,hIcon

  invoke LoadBitmap,hInstance,IDB_0 ;装入背景图片
  mov hBmpBack,eax
  invoke _SetWindowShape,hWinMain,hBmpBack ;设置窗口形状为背景图片
  invoke  GetDC,hWinMain
  mov @hDC,eax
  invoke CreateCompatibleDC,@hDC   ;建立背景及数字 DC
  mov hDcBack,eax
  invoke ReleaseDC,hWinMain,@hDC
  invoke SelectObject,hDcBack,hBmpBack
  invoke _CenterWindow,hWinMain

  ret

_Init  endp
;********************************************************************
_Quit  proc
  local @stWindow:RECT

  invoke DestroyMenu,hMenu
  invoke DeleteDC,hDcBack
  invoke DeleteObject,hBmpBack
  invoke DestroyWindow,hWinMain
  invoke PostQuitMessage,NULL

  ret

_Quit  endp
;********************************************************************
  end start


程序的分析和要点

    创建窗口的时候,窗口风格为 WS_POPUP,所以创建的窗口没有标题栏,这样的窗口适合于设置成特殊形状的窗口

  invoke CreateWindowEx,WS_EX_TOOLWINDOW,\
   offset szClassName,NULL,\
   WS_POPUP or WS_SYSMENU,\
   0,0,1,1,\
   NULL,NULL,hInstance,NULL
但是当窗口没有标题栏后,我们就无法用拖动标题栏的办法来移动窗口,如果让窗口一动不动呆在屏幕中间显然是不行的,这里有一个替代办法,我们可以响应按下鼠标左键的消息,在 WM_LBUTTONDOWN 消息中想窗口发送 WM_NCLBUTTONDOWN (非客户区鼠标按下消息) 位置在 HTCAPTION 来模拟鼠标按在标题栏中来实现移动的功能。

  .elseif eax == WM_LBUTTONDOWN
   invoke UpdateWindow,hWnd  ;即时刷新
   invoke ReleaseCapture
   invoke SendMessage,hWnd,WM_NCLBUTTONDOWN,HTCAPTION,0

责任编辑:郭瑞  联系方式  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号