win32汇编笔记

大一上学期的一些笔记:

1.一个应用程序可能有多个窗口。
2.一个应用程序实例(进程)只有一个消息队列。
3.每个窗口都有自己的窗口过程(回调函数)。
4.操作系统有自己的一个系统消息队列。
5.消息循环的各个api在user32.dll中。
6.PostMessage将消息放入指定程序的消息队列中。
SendMessage将消息直接传给对应的窗口过程(callback函数)。
PostQuitMessage将WM_QUIT消息传给消息循环。
8.RegisterClass的参数为指向结构体WndClass的指针。
9.WndClass的lpfnWndProc参数放窗口过程的地址。
10.窗口过程(callback函数)用于处理传入的消息。
11.有些实时性很强的消息如SetCursor等不通过Dispatch函数的派发,而是直接由系统调用窗口过程。
一个win32窗口程序的源程序模板:
_WinMain函数:
获取窗口句柄GetModuleHandle
注册类RegisterClassEx
建立并显示窗口CreateWindowEx  ShowWindowEx  UpdateWindowEx
消息循环GetMessage(进入user32.dll由系统取消息)  (TanslateMessage等(非必要)) DispatchMessage(进入user32.dll由系统调用窗口过程)
_ProcWinMain函数:
窗口过程,用于接收和处理消息
主函数:
call _WinMain
invoke ExitProcess NULL

12.RtlZeroMemory,@stWndClass,sizeof @stWndClass用于将结构体变量@stWndClass各成员置0.局部变量初始化十分重要,要牢记。
13.WNDCLASSEX结构体
cbsize
style        CS_VREDRAW CS_HREDRAW CS_KEYCVTWINDOW CS_DBLCLKS等等
lpfnwndproc
cbclsextra    保留
cbwndextra    保留
hinstance
hicon
hcursor        光标句柄,指定光标形状
hbrbackground    BRUSH句柄(也可以使用颜色值,如:COLOR_BACKGROUND COLOR_HIGHLIGHT COLOR_MENU COLOR_WINDOW     注:使用颜色值时后面+1)
lpszmenuname
lpszclassname
hiconsm        小图标

14.获取BRUSH的句柄:用函数GetStockObject(如:invoke getstockobject,WHITE_BRUSH)
15.CreateWindowEx,dwExStyle,lpClassName,lpWindowName,dwStyle,x,y,nWidth,nHeight,hwWndParent,hMenu,hInstance,lpParam
hMenu    菜单句柄,当dwStyle为WS_CHILD时,表示子窗口ID,子窗口没有菜单
16.WNDCLASSEX中的style(默认风格)中的值开头为CS_(CLASS STYLE),CreateWindowEx中的dwStyle的值开头为WS_(WINDOW STYLE)
17.dwExStyle的值也要牢记。。
18.hinstance是模块句柄,也就是一个应用程序实例的句柄。一个应用程序实例可能会有多个窗口。另外,一个窗口也有句柄。两者不可混淆!!
19.createwindowex返回建立的窗口的句柄。
20.类是一个应用程序实例的,所以WNDCLASSEX中才有个参数hInstance,用于取得模块句柄。
21.Button和Edit等都是子窗口。
22.程序开始时,系统会发送WM_CREATE消息到模块的消息队列中,消息循环开始后就会从消息队列读取该消息并传到窗口过程(本人猜测)

关于消息循环:
.while TURE
invoke GetMessage,addr @stmsg,NULL,0,0    (从消息队列取消息)
.break .if eax==0
invoke TranslateMessage,addr @stmsg(非必要,将一些键盘扫描码消息转为键盘ascii码消息)
invoke DispatchMessage,addr @stmsg(将消息派发给相应窗口过程)
.endw
MSG结构体:
hwnd    消息要发向的窗口句柄(注意:不是模块句柄)
message
wParam
lParam
time
pt    POINT结构体,表示消息放入消息队列时的鼠标坐标
23.createwindowex时用了某个类也就用了该类中确定的窗口过程
24.一个应用程序实例(模块)只有一个消息队列,一个消息循环,但可能有多个窗口,因此也就有可能有多个窗口过程。
25.GetMessage原型:
GetMessage,lpMsg,hWnd,wMsgfiltermin,wMsgfiltermax
lpMsg:指向一个MSG变量的指针
hWnd:表示要获取发向哪个窗口的消息。NULL表示获取本应用程序的所有消息。
后两个参数:指定获取特定编号范围的消息。0表示获取所有编号的消息。
26.WM_QUIT消息的返回值为0
27.当有按键按下或放开时触发消息:WM_KEYDOWN或WM_KEYUP或WM_SYSKEYDOWN或WM_SYSKEYUP
但其值为扫描码,TranslateMessage将其转化成WM_CHAR或WM_SYSCHAR消息。
28.遇到非键盘消息,TranslateMessage不做处理。
29.windows是抢占式多任务系统,任务间每20ms切换一次。
30.关于窗口过程:
WindowProc proc hwnd,uMsg,wParam,lParam
hwnd    要操作的窗口句柄
一个窗口过程可能会为基于同一个类的多个窗口服务,所以要指定窗口句柄。
这四个参数与MSG结构的前四个参数相同。
一条消息(MSG类型变量)中的hwnd指定了要操作哪个窗口。
不同消息后两个参数值代表的意义不同。
callback函数的返回值:
处理不同消息,返回不同值。
如:处理WM_CREATE消息时返回0表示执行成功,返回-1表示执行失败。
createwindowex时向窗口过程收到的消息:
WM_GETMINMAXINFO    获取窗口大小以便初始化
WM_NCCREATE        非客户区建立
WM_NCCALCSIZE        计算客户区大小
WM_CREATE        窗口建立
updatewindow时窗口过程收到的消息只有一条:WM_PAINT
31.单击窗口右上角关闭按钮触发WM_CLOSE消息
if uMsg == WM_CLOSE
invoke DestroyWindow…………
invoke PostQuitMessage,NULL(该函数会发送WM_QUIT消息给消息循环)  这个函数的参数就是WM_QUIT消息的MSG结构的wParam
32.结束程序时务必在摧毁窗口后用postquitmessage函数向消息循环发送WM_QUIT消息以退出消息循环。这一点很重要。
33.PostMessage,hWnd,Msg,wParam,lParam
SendMessage,hWnd,Msg,wParam,lParam
34.wsprintf是win32 api中唯一一个参数个数不定的函数。
35.FindWindow,lpClassName,lpWindowName(返回找到窗口的句柄)
36.不同消息的wParam和lParam是不同的。
37.WM_COPYDATA消息的COPYDATASTRUCT结构:
COPYDATASTRUCT
dwData    DWORD    ?    ;附加字段
cbData    DWORD    ?    ;数据长度
lpData    DWORD    ?    ;数据位置指针
COPYDATASTRUCT    ENDS
资源
38.资源源文件中
菜单 ID MENU [DISCARDABLE]指定菜单的ID值和内存属性
数值型ID的范围:1~65535    字符串在内存中的线性地址总是大于10000h
菜单项:
menuitem 菜单文字,命令ID[,选项列表]
或menuitem SEPARATOR
或popup 菜单文字[,选项列表]
命令ID:但菜单被选中时会发送WM_COMMAND消息,消息的参数就是命令ID
39菜单的装载:
菜单可以在createwindowex中的参数hMenu指定句柄,那么菜单句柄如何获得?用api:LordMenu,hInstance,菜单的ID
40.WM_COMMAND的两个消息:
wParam高位=wNotifyCode    通知码
wParam低位=wID        命令ID
lParam=hwndCtl        发送消息的子窗口句柄(工具栏、按钮等)(对于菜单或加速键引起的WM_COMMAND消息则lParam为0)
菜单消息的通知码是0,加速键消息的通知码是1
程序运行中动态修改菜单:
AppendMenu,hMenu,uFlag,uIDNewItem,lpNewItem
InsertMenu,hMenu,uPosition,uFlags,uIDNewItem,lpNewItem
ModifyMenu,hMenu,uPosition,uFlags,uIDNewItem,lpNewItem
DeleteMenu,hMenu,uPosition,uFlags
RemoveMenu,hMenu,uPosition,uFlags
uFlags一般用两种值:MF_BYCOMMAND  MF_BYPPOSITION
对于popup菜单
DeleteMenu:全删
RemoveMenu:仅移去菜单项,菜单在内存中还是存在的(可以在其他地方引用)
对于非popup菜单,两者相同
41.系统菜单:指按下了标题栏图标后弹出的菜单。
42.选中系统菜单项发送WM_SYSCOMMAND消息
系统菜单的句柄:GetSystemMenu,hWnd,FALSE
系统菜单的默认菜单项的命令ID(系统预定义):
保存    SC_RESTORE
移动    SC_MOVE
大小    SC_SIZE
最小化    SC_MINIMIZE
最大化    SC_MAXIMIZE
关闭    SC_CLOSE
43.右键弹出菜单
TrackPopupMenu,hMenu,uFlags,x,y,nReserved,hWnd,lpRect
该函数执行后在x,y处弹出属于hWnd窗口的菜单(即WM_COMMAND消息发往该窗口)(x,y以屏幕左上角为基准)
uFlags:一般用TPM_LEFTALIGN
该参数还可用于指定用左键还是右键选定菜单项:TPM_LEFTBUTTON   TPM_RIGHTBUTTON
lpRect指向一个RECT结构,用于指定一个区域,在这个区域外单击鼠标菜单才会消失,如果为NULL,则在菜单外单击,菜单就会消失。
在客户区右击弹出菜单,所以要处理WM_RBUTTONDOWN消息。在该消息中调用TrackPopupMenu
一般在单击处弹出菜单,所以要要获取鼠标坐标GetCursorPos,lpPoint
lpPoint指向POINT结构
POINT    STRUCT
x  DWORD  ?
y  DWORD  ?
POINT    ENDS
LordMenu载入的不是popup菜单,popup只能在第二层及以下。用GetSubMenu
invoke GetSubMenu,hMenu,nPos
.if eax
mov hSubMenu,eax
.endif
nPos:菜单项的索引,从0开始
右键菜单一般性代码范例:
local:@stPos:POINT
……
invoke GetCursor,addr @stPos
invoke TrackPopupMenu,hSubMenu,TPM_LEFTALIGN,@stPos.x,@stPos.y,NULL,hWnd,NULL
44.菜单将激活,即用户在菜单上按动鼠标时,windows在菜单弹出之前会向窗口过程发送WM_INITMENU消息,可以在这个消息的处理中进行菜单项的检测和设置:
GetMenuState,hMenu,uId,uFlags
GetMenuState函数的返回值:
失败返回-1
成功则:
MF_CHECKED
MF_DISABLED
MF_GRAYED
MF_HILITE高亮
MF_MENUBARBREAK
MF_MENUBREAK
MF_SEPARATOR
以上的组合值
如何检测菜单状态:
invoke GetMenuState,hMenu,IDM_XXX,MF_BYCOMMAND
.if eax&MF_CHECKED(表示菜单项选中)
…………
.endif

EnableMenuItem,hMenu,uIDEnableItem,uEnable(uEnable取值:MF_ENABLED  MF_DISABLED  MF_GRAYED)(菜单项在可用、禁用、灰化之间转化)
CheckMenuItem,hMenu,uIDCheckItem,uCheck(uCheck取值:MF_CHECKED  MF_UNCHECKED)
CheckMenuRadioItem,hMenu,idFist,idLast,idCheck,uFlags
45.没有与窗口相连的菜单要用DestroyMenu来释放内存
SetMenu,hWnd,hMenu用于在不同情况下给程序以不同的菜单(如未打开文件和打开文件下窗口的菜单是不同的,这就需要在rc文件中建多个菜单)

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>