📄 用masmplus学习汇编语言 7.txt
字号:
用MasmPlus学习汇编语言 7
相关的例子:下载>>> 作者:Zoologist 于2008-3-16上传
--------------------------------------------------------------------------------
我很喜欢使用Delphi,至少使用它编程的时候不用担心界面的问题,“拖拖拉拉”就能
完成一个Windows标准程序的界面。这次我将介绍如何使用汇编语言设计简单的界面。
一.如何使用 Static ?
这个东西就是在界面上显示一行文字的东西,Delphi中叫做Label。创建的方法很简单,
和创建窗口差不多,就是使用 CreateWindowEx API,我们告诉系统,我要建立一种叫做static
的东西,这个东西放在我建立好的窗口上,窗口的handler是static,程序的handler是hInst,
于是写出来就是这个样子:
INVOKE CreateWindowEx, NULL, CTXT("static"), addr szText01,\
WS_CHILD or WS_VISIBLE or SS_NOTIFY,\
53, 66, 200, 69, hWnd, 2001, hInst, NULL
对照原形:
HWND CreateWindowEx(
DWORD dwExStyle,
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam
);
各个含义可以猜得八九不离十。
下面的问题就是怎么向上面写字?我们使用 SetWindowText API,定义如下:
BOOL SetWindowText(
HWND hWnd,
LPCTSTR lpString
);
我们前面一直都在用,ShowMessage API 这个定义一看就清楚。
最后,我们要在上面写点什么呢?就写一下当前的时间吧。用 GetLocalTime API
可以获得当前的日期时间,不过需要留心一下,SYSTEMTIME 结构体中的成员都是WORD,
直接使用 invoke 压入进行格式转换会出现莫名其妙的错误,具体说来就是:
invoke wsprintf,addr szBuffer,CTXT("%u %u"),lpLocalTime.wYear,lpLocalTime.wMonth
这样用是不对的,运行起来除了第一个,其余的都不对。
程序如下,我们将显示时间写在WM_SIZE消息中,每次改变窗口都会显示现在的时间。
惯例还要说点需要注意的问题:注意指定的长宽,要是显示不下,有可能出现字符截断
的情况,或者自己转到了下一行的情况哦。
参考:
1.CreateWindowEx http://msdn2.microsoft.com/en-us/library/ms632680(VS.85).aspx
2.SetWindowText http://msdn2.microsoft.com/en-us/library/ms633546(VS.85).aspx
3.GetLocalTime http://msdn2.microsoft.com/en-us/library/ms724338(VS.85).aspx
二. Button
象上一个程序一样,button 也是使用CreateWindowEx建立的。比如,我们用下面的
语句就可以建立2个button,不同的地方是,这里我们特地定义了ButtonID1和ButtonID2。
简单的说,这个只是一个编号,使给我们后面响应命令用的。
INVOKE CreateWindowEx, NULL, CTEXT("button"), CTEXT("BT1"),\
WS_CHILD or WS_VISIBLE or WS_TABSTOP,\
15, 18, 80, 25, hWnd, ButtonID1, hInst, NULL
mov hButton1, eax
INVOKE CreateWindowEx, NULL, CTEXT("button"), CTEXT("BT2"),\
WS_CHILD or WS_VISIBLE or WS_TABSTOP,\
103, 19, 80, 25, hWnd, ButtonID2, hInst, NULL
mov hButton2, eax
完整的程序:
;MASMPlus 代码模板 - 普通的 Windows 程序代码
.386
.Model Flat, StdCall
Option Casemap :None
Include windows.inc
Include user32.inc
Include kernel32.inc
Include gdi32.inc
includelib gdi32.lib
IncludeLib user32.lib
IncludeLib kernel32.lib
include macro.asm
ButtonID1 equ 2003
ButtonID2 equ 2004
WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
.DATA
szClassName db "MASMPlus_Class",0
.DATA?
hInstance dd ?
hButton1 dd ?
hButton2 dd ?
.CODE
START:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke WinMain,hInstance,NULL,NULL,SW_SHOWDEFAULT
invoke ExitProcess,0
WinMain proc hInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,CmdShow:DWORD
LOCAL wc :WNDCLASSEX
LOCAL msg :MSG
local hWnd :HWND
mov wc.cbSize,sizeof WNDCLASSEX
mov wc.style,CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW
mov wc.lpfnWndProc,offset WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_BTNFACE+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,offset szClassName
invoke LoadIcon,hInst,100
mov wc.hIcon,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
mov wc.hIconSm,0
invoke RegisterClassEx, ADDR wc
invoke CreateWindowEx,NULL,ADDR szClassName,CTXT("http://www.aogosoft.com"),WS_OVERLAPPEDWINDOW,200,200,400,200,NULL,NULL,hInst,NULL
mov hWnd,eax
INVOKE CreateWindowEx, NULL, CTEXT("button"), CTEXT("BT1"),\
WS_CHILD or WS_VISIBLE or WS_TABSTOP,\
15, 18, 80, 25, hWnd, ButtonID1, hInst, NULL
mov hButton1, eax
INVOKE CreateWindowEx, NULL, CTEXT("button"), CTEXT("BT2"),\
WS_CHILD or WS_VISIBLE or WS_TABSTOP,\
103, 19, 80, 25, hWnd, ButtonID2, hInst, NULL
mov hButton2, eax
invoke ShowWindow,hWnd,SW_SHOWNORMAL
invoke UpdateWindow,hWnd
StartLoop:
invoke GetMessage,ADDR msg,NULL,0,0
cmp eax, 0
je ExitLoop
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
jmp StartLoop
ExitLoop:
mov eax,msg.wParam
ret
WinMain endp
WndProc proc hWin:DWORD,uMsg:DWORD,wParam :DWORD,lParam :DWORD
LOCAL szBuffer[10] :BYTE
.if uMsg==WM_CREATE
.elseif uMsg == WM_DESTROY
invoke PostQuitMessage,NULL
.elseif uMsg == WM_COMMAND
mov eax,wParam
.IF ax==ButtonID1 ;我们在这里响应按键的动作
shr eax,16
.IF ax==BN_CLICKED
invoke wsprintf,addr szBuffer,CTXT("%s"),CTEXT("Button1")
invoke MessageBox,hWin,addr szBuffer,NULL,NULL
.ENDIF
.ENDIF
.IF ax==ButtonID2
shr eax,16
.IF ax==BN_CLICKED
invoke wsprintf,addr szBuffer,CTXT("%s"),CTEXT("Button2")
invoke MessageBox,hWin,addr szBuffer,NULL,NULL
.ENDIF
.ENDIF
.else
invoke DefWindowProc,hWin,uMsg,wParam,lParam
.endif
ret
WndProc endp
END START
参考:
1.Iczelion's Win32 Assembly 教程 Tutorial 9: Child Window Controls
三.透明效果的实现
我们要实现透明窗口的效果,必须使得窗口拥有 WS_EX_LAYEDER 扩展属性,当然可以在创建的时候
直接指定,这里我们绕个弯,多讲一些,使用 GetWindowLong 取当前窗口的 GWL_EXSTYLE属性,加上
WS_EX_LAYERED 属性后再用 SetWindowLong设置回去。
指定透明的API是 SetLayeredWindowAttributes 原形如下:
第一个参数给定窗口的handler;第二个参数,给出一个眼色值;第三个参数给出透明度的值,
0是最透明,最大255是最不透明的;后面是标志位,
LWA_COLORKEY =1 将crKey给出的颜色指定为透明色
LWA_ALPHA =2 将 bAlpha 给出的透明度作为窗口的透明度
我们的程序中只使用了透明的功能。
;MASMPlus 代码模板 - 普通的 Windows 程序代码
.386
.Model Flat, StdCall
Option Casemap :None
Include windows.inc
Include user32.inc
Include kernel32.inc
Include gdi32.inc
includelib gdi32.lib
IncludeLib user32.lib
IncludeLib kernel32.lib
include macro.asm
ButtonID1 equ 2003
ButtonID2 equ 2004
LWA_ALPHA equ 2
LWA_COLORKEY equ 1
WS_EXD_LAYERED equ 80000h
WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
.DATA
szClassName db "MASMPlus_Class",0
bAlpha dd 0FFh
.DATA?
hInstance dd ?
hButton1 dd ?
hButton2 dd ?
hWnd HWND ?
.CODE
START:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke WinMain,hInstance,NULL,NULL,SW_SHOWDEFAULT
invoke ExitProcess,0
WinMain proc hInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,CmdShow:DWORD
LOCAL wc :WNDCLASSEX
LOCAL msg :MSG
mov wc.cbSize,sizeof WNDCLASSEX
mov wc.style,CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW
mov wc.lpfnWndProc,offset WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_BTNFACE+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,offset szClassName
invoke LoadIcon,hInst,100
mov wc.hIcon,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
mov wc.hIconSm,0
invoke RegisterClassEx, ADDR wc
invoke CreateWindowEx,NULL,ADDR szClassName,CTXT("http://www.aogosoft.com"),WS_OVERLAPPEDWINDOW,200,200,400,200,NULL,NULL,hInst,NULL
mov hWnd,eax
INVOKE CreateWindowEx, NULL, CTEXT("button"), CTEXT("虚"),\
WS_CHILD or WS_VISIBLE or WS_TABSTOP,\
15, 18, 80, 25, hWnd, ButtonID1, hInst, NULL
mov hButton1, eax
INVOKE CreateWindowEx, NULL, CTEXT("button"), CTEXT("实"),\
WS_CHILD or WS_VISIBLE or WS_TABSTOP,\
103, 19, 80, 25, hWnd, ButtonID2, hInst, NULL
mov hButton2, eax
invoke GetWindowLong,hWnd,GWL_EXSTYLE
or eax,WS_EXD_LAYERED
invoke SetWindowLong,hWnd,GWL_EXSTYLE,eax
invoke SetLayeredWindowAttributes,hWnd,0,bAlpha,LWA_ALPHA
invoke ShowWindow,hWnd,SW_SHOWNORMAL
invoke UpdateWindow,hWnd
StartLoop:
invoke GetMessage,ADDR msg,NULL,0,0
cmp eax, 0
je ExitLoop
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
jmp StartLoop
ExitLoop:
mov eax,msg.wParam
ret
WinMain endp
WndProc proc hWin:DWORD,uMsg:DWORD,wParam :DWORD,lParam :DWORD
LOCAL szBuffer[10] :BYTE
.if uMsg==WM_CREATE
.elseif uMsg == WM_DESTROY
invoke PostQuitMessage,NULL
.elseif uMsg == WM_COMMAND
mov eax,wParam
.IF ax==ButtonID1 ;虚
shr eax,16
.IF ax==BN_CLICKED
mov eax,100
mov bAlpha,eax
.ENDIF
.ENDIF
.IF ax==ButtonID2 ;实
shr eax,16
.IF ax==BN_CLICKED
mov eax,255
mov bAlpha,eax
.ENDIF
.ENDIF
invoke SetLayeredWindowAttributes,hWnd,0,bAlpha,LWA_ALPHA ;设置透明
.else
invoke DefWindowProc,hWin,uMsg,wParam,lParam
.endif
ret
WndProc endp
END START
当点击 “虚” 按钮时,窗口会变得透明,当点击 “实” 按钮时,窗口会恢复。
有兴趣的读者还可以试验一下更多的功能。需要注意的是
LWA_ALPHA LWA_COLORKEY WS_EXD_LAYERED 在SDK中并没有定义,需要在程序中定义一下。
根据上面的例子,我们还可以编写隐藏任务栏的小程序。同样是设置两个按钮,
一个是隐藏,一个是显示。然后在程序中加入下面的代码即可:
invoke FindWindow,CTXT('Shell_TrayWnd'),NULL
mov hDesktop,eax
.IF ax==ButtonID1 ;隐藏
invoke ShowWindow,hDesktop,SW_HIDE
.ENDIF
.IF ax==ButtonID2 ;显示
invoke ShowWindow,hDesktop,SW_RESTORE
.ENDIF
至于放到什么地方,请读者发挥自己的想象力~
参考:
1.SetLayeredWindowAttributes http://msdn2.microsoft.com/en-us/library/ms633540(VS.85).aspx
SetLayeredWindowAttributes Function
The SetLayeredWindowAttributes function sets the opacity and transparency color key of a layered window.
Syntax
BOOL SetLayeredWindowAttributes(
HWND hwnd,
COLORREF crKey,
BYTE bAlpha,
DWORD dwFlags
);
Parameters
hwnd
[in] Handle to the layered window. A layered window is created by specifying WS_EX_LAYERED when creating the window with the CreateWindowEx function or by setting WS_EX_LAYERED via SetWindowLong after the window has been created.
crKey
[in] COLORREF structure that specifies the transparency color key to be used when composing the layered window. All pixels painted by the window in this color will be transparent. To generate a COLORREF, use the RGB macro.
bAlpha
[in] Alpha value used to describe the opacity of the layered window. Similar to the SourceConstantAlpha member of the BLENDFUNCTION structure. When bAlpha is 0, the window is completely transparent. When bAlpha is 255, the window is opaque.
dwFlags
[in] Specifies an action to take. This parameter can be one or more of the following values.
LWA_COLORKEY
Use crKey as the transparency color.
LWA_ALPHA
Use bAlpha to determine the opacity of the layered window.
Return Value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.
--------------------------------------------------------------------------------
<<<上一篇 欢迎访问AoGo汇编小站:http://www.aogosoft.com/ 下一篇>>>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -