这是一个简单的记事本的窗口过程
1 WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM 2 3 LOCAL winRect:RECT 4 LOCAL editWidth:DWORD 5 LOCAL editHeight:DWORD 6 7 .IF uMsg==WM_DESTROY 8 invoke PostQuitMessage,NULL 9 .ELSEIF uMsg==WM_CREATE10 ;创建一个编辑框11 invoke CreateWindowEx,WS_EX_CLIENTEDGE,offset editClass,NULL,\12 WS_CHILDWINDOW OR WS_VISIBLE OR WS_VSCROLL OR WS_HSCROLL OR WS_MAXIMIZE OR\13 ES_AUTOHSCROLL or ES_AUTOVSCROLL or ES_MULTILINE ,\14 0,0,300,300,hWnd,NULL,hInstance,NULL15 mov hEdit,eax16 17 .elseif uMsg==WM_SIZE18 ;获取当前窗体的x,top,y,bottom19 20 invoke GetClientRect,hWnd,addr winRect21 22 ;计算出窗体的新宽度和高度23 mov eax,winRect.right24 sub eax,winRect.left 25 mov editWidth,eax26 27 mov eax,winRect.bottom28 sub eax,winRect.top29 mov editHeight,eax30 31 ;改变文本编辑框的宽度和高度32 invoke MoveWindow,hEdit,0,0,editWidth,editHeight,TRUE33 34 35 .ELSE36 invoke DefWindowProc,hWnd,uMsg,wParam,lParam 37 ret38 .ENDIF39 40 xor eax,eax41 ret42 WndProc endp
API主要调用了CreateWindowEx,GetClientRect,MoveWindow
一些常用的窗口风格预定义值
窗口风格的预定义预定义值 含义WS_OVERLAPPED 普通的重叠式窗口WS_POPUP 弹出式窗口(没有标题栏)WS_CHILD 子窗口WS_MINIMINZE 初始状态是最小化WS_VISIBLE 初始状态是可见的WS_DISABLED 初始状态是被禁止的WS_MAXIMIZE 初始状态是最大化的WS_BORDER 单线条边框WS_DLGFRAME 对话框类型的边框WS_VSCROLL 带垂直滚动条WS_HSCROLL 带水平滚动条WS_SYSMENU 带系统菜单(即带标题栏左上角的图标)WS_THICKFRAME 可以拖动调整大小的边框WS_MINIMIZEBOX 有最小化按钮WS_MAXIMIZEBOX 有最大化按钮为了容易理解,Window也为一些定义取了一些别名,同时,由于窗口的风格往往是几种风格的组合,所以Window也预定义了一些组合值,如下: 等效的窗口风格预定义值预定义值 等效值WS_CHILDWINDOW WS_CHILDWS_TILED WS_OVERLAPPEDWS_ICONIC WS_MINIMIZEWS_SIZEBOX WS_THICKFRAMEWS_OVERLAPPEDWINDOW WS_OVERLAPPED or WS_CAPTION or WS_THICKFRAME or WS_MINIMIZEBOX or WS_MAXIMIZEBOXWS_TILEDWINDOW WS_OVERLAPPEDWINDOWWS_POPUPWINDOW WS_POPUP or WS_BORDER or WS_SYSMENUWin32窗口风格的一些扩展,它们是一些以WS_EX_开头的预义值,主要定义了一些特殊的风格,如下:预定义值 含义WS_EX_TOPMOST 总在顶层的窗口WS_EX_ACCEPTFILES 允许窗口进行鼠标拖放操作WS_EX_TOOLWINDOW 工具窗口(很窄的标题栏)WS_EX_WINDOWEDGE 立体感的边框WS_EX_CLIENTEDGE 客户区立体边框WS_EX_OVERLAPPEDWINDOW WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGEWS_EX_PALETTEWINDOW WS_EX_WINDOWEDGE or WS_EX_TOOLWINDOW or WS_EX_TOPMOST调用CreateWindowEx时窗口过程收到的消息----------------------------------------------------------------------消息发生 说明------------------------------------------------------------------------------WM_GETMINMAXINFO 获取窗口大小,以便初始化WM_NCCREATE 非客户区开始建立WM_NCCALCSIZE 非客户区大小WM_CREATE 窗口建立-----------------------------------------------------------------------调用ShowWindow时窗口过程收到的消息-------------------------------------------------------------------------------------------消息发生 说明-------------------------------------------------------------------------------------------WM_SHOWWINDOW 显示窗口WM_WINDOWPOSCHANGING 窗口位置准备改变WM_ACTIVATEAPP 窗口准备激活WM_NCACTIVATE 激活状态改变WM_GETTEXT 取窗口名称(显示标题栏目)WM_ACTIVATE 窗口准备激活WM_SETFOCUS 窗口获取焦点WM_ERASEBGND 需要擦除背景WM_WINDOWPOSCHEANGED 窗口位置已经改变WM_SIZE 窗口大小已经改变WM_MOVE 窗口位置已经移动--------------------------------------------------------------------------------------------------------------------------调用DestroyWindow时窗口过程收到消息
---------------------------------------------------------------------------------------------------------------------消息发生 说明-----------------------------------------------------------------------------------------------------------WM_NCACTIVATE 窗口激活状态WM_ACTIVATE 窗口准备非激活WM_ACTIVATEAPP 窗口准备非激活WM_KILLFOCUS 失去焦点WM_DESTROY 窗口即将被摧毁WM_NCDESTROY 窗口的非客户区及所有子窗口已经被摧毁-----------------------------------------------------------------------------------------------------------------------------------DefWindowProc对一些消息的默认处理方式-----------------------------------------------------------------------------------------------------------------------------------消息 DefWindowProc的处理方式---------------------------------------------------------------------------------------------------------------------------------WM_PAINT 发送WM_ERASEBKGND消息来擦除背景WM_ERASEBKGND 用窗口类结构中的hrBackground刷子来绘画窗口背景WM_CLOSE 调用DestroyWindow来摧毁窗口WM_NCLBUTTONDBLCLK 这是非客户区(如标题栏)鼠标双击消息,DefWindowProc测试鼠标的位置,然后再采 取相应的措施,如标题栏双击将最大化和恢复窗WM_NCLBUTTONUP 这是非客户区鼠标释放消息,同样,DefWindowProc测试的位置然后再采用相相应的 措施,如鼠标在"关闭"按钮的位置释放将导致发送WM_CLOSE消息WM_NCPAINT 非客户区绘制消息,DefWindowProc将绘制边框和客户区--------------------------------------------------------------------------------------------------------------------------------------------------窗口建立的过程GetModuleHandle---------->RtlZeroMemory---->LoadCursor------>RegisterClassEx----->CreateWindowEx---->ShowWindow--->UpdateWindowGetModuleHandle ;//得到窗口句柄
LoadMenu//得到窗口的菜单句柄LoadAccelerator;//得到右键句柄得到鼠标位置
GetCursorPos,addr @stPos;其中@stPos是 一个POINT类型的变量不同应用程序之间的窗口是可以发送消息的,通过SendMessage或者PostMessage函数,用法如下:
invoke SendMessage ,hWnd,Msg,wParam,lParam invoke PostMessage,hWnd,Msg,wParam,lParam如果要改变窗口的光标,正确的办法是用SetClassLong函数改变窗口类的属性,这个函数的使用方法如下:
invoke SetClassLong,hWnd,nIndex,dwNewLong这个函数用来改变窗口的属性,所以可以改变类中的光标设定,hWnd用来设定一个这个类建立的某个窗口句柄,nIndex参数指定要改变窗口类的哪个属性,可以指定为GCL_HBRBACKGROUND,GCL_HCURSOR,GCL_HICON,GCL_HMODULE,GCL_MENUNAME,GCL_STYLE或GCL_WNDPROC等,它们分别表示 要改变的窗口类的背景色、光标、图标、Hinstance,菜单、风格或窗口过程地址,读者可以用这个函数来改变一个窗口类的几乎所有属性,程序中通过这个函数将窗口的光标在不同的光标句柄之间切换: invoke SetClassLong,hWnd,GCL_HCUROSR,hCur1或hCur2在资源脚本中定义的是控件的ID,当这些子窗口控件被创建以后同样会有一个窗口句柄,但既然它们不是由我们自己创建的,那么怎么知道它们的窗口句柄呢?有一个函数可以从ID中获取句柄: invoke GetDlgItem,hDlg,dwIDDlgItem mov hDlgItem,eax 函数的输入参数是对话框和ID值,返回值是子窗口句柄:返过来,有两种方法可以从子窗口句柄获取ID: (1) invoke GetDlgCtrlID,hWndCtrl;输入子窗口句柄,返回值是控件ID (2) invoke GetWindoLong,hWndCtrl,GWL_ID 当需要向控件发送消息的时候,当然可以先用GetDlgItem获取子窗口句柄再用SendMessage函数,但有一个 更为简便: invoke SendDlgItemMessage,hDlg,dwIDDlgItem,Msg,wParam,lParam 这个函数可以直接向控件发送消息,只需要在参数中指定对话框句柄和子窗口ID(注意,并没有PostDlgItemMessage这样的函数!)。 单选钮和复选框 单选钮和复选框都是基于Button类的,只不过它们的窗口分别是BS_RADIOBUTTON和BS_CHECKBOX. 既然它们是特殊“按钮”,所以和它们有关的函数都带有“Button"一词,查看一个单选钮或复选框是否可以 用下面的函数来检测: invoke IsDlgButtonChecked,hDlg,nIDButton 函数的返回值可能是BST_CHECKED(选中状态),BST_INDETERMINATE(3态复选框的灰化状态)或BST_UNCHECKED(未选中状态)。也 可以用向子窗口控件发送BM_GETCHECK消息的方法来检测,返回值和上面的函数是一样的。 如果想设置单选按钮或复选框的状态,可以使用下面蝗语句: invoke CheckDlgButton,hDlg,nIDButton,uCheck 参数uCheck用BST_CHECKED,BST_INDETERMINATE或BST_UNCHECKED来表示需要设置的状态,含义同上。向控件发送BM_SETCHECK消息 也可以取得同样的效果,这时消息的wParam中放置需要的状态。 复选框是不互斥的,所以 可随意主设置状态。而对于BS_RADIOBUTTON风格的单选按钮来说,并不是把某个按钮设置为选中以后,如果不是手动把同组的其他按钮全部 改为非选 中状态(逐个地调用 CheckDlgButton),就会看到同是圾两个单选钮是选 中的。但把同组的所有单选钮逐个地设置显得有点麻烦,所以针对单选钮有个专用函数: invoke CheckRadioButton,hDlg,nIDFirstButton,nIDLastButton,nIDCheckedButton 文本编辑控件 文本编辑器是基于Edit类的控件,可以用缩写EDITTEXT定义,读者可以在文本编辑控件中输入并编辑文本。每当用户在文本编辑控件中输入一个字符的时候,控件就会向对话框过 程发送一个WM_COMMAND消息,所以在例子程序中,当在自定义文字的编辑框中每输入一个字,标题栏文字就会马上改变以。 当获取编辑框中的文本有多种方法,可以用GetWindowText,也可以用发送WM_GETTEXT消息的办法,要设置文本,同样可以用SetWindowText或发送WM_SETTEXT,但最简便的办法还是 使用下的函数: invoke GetDlgItemText,hDlg,nIDDlgItem,ipString,nMaxCount;取文本 invoke SetDlgItemText,hDlg,nIDDlgItem,lpString;设置文本 在实际使用中,经常要在文本编辑控件中输入输出值型参数,将文本转换为数值比较麻烦,把数值转换为文本也要经过一个wsprintf调用,为了简化 操作,Windows提供了两个 函数来处理这个问题: invoke GetDlgItemInt,hDlg,nIDDlgItem,uValue,bSigned;取控件中的数值 invoke SetDlgItemInt,hDlg,nIDDlgItem,lpTranslated,bSigned;设置控件中的数值 下面的例子将IDC_EDIT的输入最大长度定为10个字符: invoke SendDlgItemMessage,hDlg,IDC_EDIT,EM_LIMITTEXT,10,NULL invoke SendDlgItemMessage,hDlg,IDC_EDIT,EM_SETREADONLY,TRUE,NULL;只读 invoke SendDlgItemMessage,hDlg,IDC_EDIT,EM_SETREADONLY,FALSE,NULL;可写 滚动条 和其他子窗口控件发送WM_COMMAND消息不同,水平滚动条向对话框窗口发送WM_HSCROLL消息,而垂直滚动条则发送WM_VSCROLL消息,所以针动 对两种方式的滚动条分别处理不同的 消息: WM_xSCROLL消息的参数如下所示: wParam的低16位==nScrollCode;动作码 wParam的高16位== nPos;滚动条当前位置 lParam==hwndScrollBar;滚动条控件的窗口句柄 组合框 3种类型的组合框: CBS_SIMPLE,CBS_DROPDOWN,CBS_DROPDOWNLIST 组合框 中还有几种常用的、可以附加的风格: CBS_AUTOSCROLL 输入过长的文本时输入框自动卷动 CBS_LOWERCASE 自动将所有的文本转换成小写 CBS_SORT 自动将插入的文本项排序 CBS_UPPERCASE 自动将所有的文本转换成大写 组合框消息消息 Wparam lParam 说明CB_ADDSTRING 0 字符串地址 把一个字符串添加到列表中CB_INSERTSTRING 位置索引 字符串地址 把一个字符插入到列表中CB_FINDSTRING 开始查找的位置索引 查找的字符串 在列表中查找以lParam字符中开头的项,的巧劲则返回 位置索引,未找到返回CB_ERRCB_FINDSTRINGEXACT 位置索引 查找的字符串 精确查找字符串CB_DELTESTRING 位置索引 0 删除一个列表项CB_RESTECONTEXT 0 0 删除所有了列表项CB_GETLBTEXT 位置索引 缓冲区地址 获取指定列表项的字符串,缓冲必须足够大CB_GETLBTEXTLEN 位置索引 0 获取指定列表项的字符串长度CB_GETCOUNT 0 0 获取列表项的总数CB_SETCURSEL 位置索引 0 选中一个列表项,并将列表项中的文字拷贝到编辑控件中CB_SELECTSTRING 开始查找的位置索引 字符串地址 查找以lParam指定的字符中开始的列表项,如果找到则选中 中它将字符串拷贝到编辑框 中CB_GETCURSET 0 0 获取当前选中位置索引,没有选中的项目则返回CB_ERRCB_SHOWDROPDOWN 状态 0 打开(状态为TRUE)或收起(状为FALSE)下拉列表CB_GETDROPEDSTATE 0 0 检测列表的当前下拉状态,返回TRUE表示拉下,FALSE表示收起当用户在组合框中进行选 择操作时,Windows向对话框过程发送WM_COMMAND消息,消息中的WParam参数的低16位是组合框,高16位是通知码,用来表示用户的操作,通知码的定义: 用户操作组合框后的通知码 通知码 说明 CBN_SELCHANGE 用户将要选择一个项目(鼠标移动到了这个项目上) CBN_CLOSEUP 下拉列表关闭(可能是选 择完成也可能是取消选择) CBN_SELENDOK 用户完成选择 CBN_SELENDCANCEL 用户取消选择(鼠标移动到了某个项目上,但并没有按下而是点击了其控件,或按动了ESC键) CBN_DBLCLK 在CBS_SIMPLE的组合框中双击了一个列表项 CBN_DROPDOWN 用户打开了下拉框(按动了编辑框边的下拉按钮) 当列表框是LBS_NOTIFY风格的时候,用户有所动作时列表框 会向父窗口发送WM_COMMAND消息,同时在wParam的高16位中指定 通知码,列表框的通知码种类很少,基本上就是以下几种: .LBN_DBLCLK 用户双击了一个项目 .LBN_ERRSPACE 插入项目时无法申请到足够的内在 .LBN_KILLFOCUS 输入焦点被切换到其他控件中列表丢失了焦点 .LBN_SELCANCEL 用户撤销了一个选择 .LBN_SELCHANGE 选定状态改变 .LBN_SETFOCUS 列表框得到了焦点 列表框通知父窗口是通过发送WM_COMMAND消息,而程序控制列表框的时候是通过向列表框发送消息来完成的,常用的列表框消息如下: 消息 wParam lParam 说明 LB_ADDSTRING 0 字符串地址 添加一个项目,返回加入后的索引 LB_DELETESTRING 位置索引 0 删除一个项目,返回剩余的项数 LB_FINDSTRING 开始索引 字符串地址 查找以字符串开头的项目,找到则返回位置索引,未找到则返回LB_ERR LB_FINDSTRNGEXACT 开始索引 字符串地址 精确查找一个项目,返回值同上 LB_GETANCHORINDEX 0 0 返回多选列表框多选时的起始位置 LB_GETACRETINDEX 0 0 多选框中的当前焦点项目焦点位置 LB_GETCOUNT 0 0 返回列表框中的项目总数 LB_GETCURSETL 0 0 返回列表框中当前选中的项目 LB_GETSEL 位置索引 0 检测指定项目的选中状态,返回非0为选中,返回0为未选 中 LB_GETSELCOUNT 0 0 返回列表框中选中项目的总数 LB_GETSELLITEMS 最大项数 缓冲区地址 返回多选列表框的选中项目索引列表到缓冲区中 LB_GETTEXT 位置索引 缓冲区地址 返回某个项目的字符串 LB_GETTEXTLEN 位置索引 0 返回某个项目的字符串长度 LB_GETTOPINDEX 0 0 返回当前可见的第一个项目位置 LB_INSERTSTRING 插入位置 字符串地址 在指定位置插入一个项目 LB_RESETCONTENT 0 0 删除所有项目 LB_SELECTSTRING 开始位置 字符串地址 将以指定字符串开头的项目选 中 LB_SELITEMRANGE 选择状态 范围 在多选框中将一个范围选中或清除 LB_SETCURSEL 位置索引 0 在单选框中选 择一个项目 LB_SETSEL 选择状态 位置索引 在多选框中将一个项目选中或清除 LB_SETTOPINDEX 位置索引 0 滚动显示到指定的项目 LB_DIR 属性 文件通配符 搜索目录并将符合文件通配符的文件名加入到列表框中 在这些消息中LB_DIR 是个比较有趣的消息,它可以指定目录中的文件名自动列出来并加入到列表框中,如例子中用*.*将当前目录 的全冲毁文件名加到列表框中。LB_DIR 消息中wParam参数可以指定的属性可以是以下值的组合: .DDL_ARCHIVE 加入归档属性的文件 .DDL_DIRECTORY 加入目录 .DDL_DRIVES 加入驱动器名 .DDL_HIDDEN 包含隐含文件 .DDL_READONLY 包含只读文件 .DDL_READWRITE 包含可读写的文件 .DDL_SYSTEM 包含系统文件 申请一个定时器使用SetTimer函数,函数的使用方法如下: invoke SetTimer,hWnd,nIDEvent,uElapse,lpTimeFunc hWnd参数是WM_TIMER消息发往的窗口句柄;nIDEvent参数是一个用户指定的任意整数,用来标识 一个程序中的多个定时 器 ;uElapse是时间周期,以ms为单位,这个参数是必须指定的;lpTimerFunc是定时器过程。 撤消定时器的函数是KillTimer,该函数的使用方法: invoke KillTimer,hWnd,uIDEvent 参数 hWnd,uIDEvent就是申请时用来的参数 申请定时器的有两个方法: 第一个: invoke SetTimer,hWnd,ID_TIMER,250,NULL 这时参数lpTimeFunc必须为NULL 第二种: invoke SetTimer,NULL,NULL,1000,addr _ProcTimer 把返回的值保存下来,以便注销是使用。 定时器过程如下定义: TimeProc proc hwnd,uMsg,idEvent,dwTime 显示设备的颜色深度可以用以下函数获取: invoke GetDeviceCaps,hDc,PLANES mov ebx,dwPlanes invoke GetDeviceCaps,hDc,BITSPIXEL mul ebx mov dwColorDepth,eax 第一个函数调用返回DC的色彩平面数,第二函数调用返回每个像素的色彩位数,颜色深度最后可以通过dwPlanes乘以dwBitsPixel得到.Window也提供了其他一些坐标映射方法供程序员使用,可以用SetMap Mode函数来为一个DC设置新的坐标映射方法: invoke SetMapMode,hDc,iMapMode 参数iMapMode可以取下面的值: Windows中可用的坐标映射方式映射方法 原点 逻辑单位 X正方向 Y正方向MM_TEXT(默认方式) 左上 像素 右 下MM_HIENGLISH 左上 0.001英寸 右 上MM_LOENGLISH 左上 0.001英寸 右 上MM_HIMETRIC 左上 0.001毫米 右 上MM_LOMETRIC 左上 0.1毫米 右 上MM_TWIPS 左上 1/1440英寸 右 上MM_ISOTROPIC 可变 可变(x=y) 可变 可变MM_ANISOTROPIC 可变 可变(x!=y) 可变 可变最后两种映射方式提供了更灵活了选择,设置为这两种映射方式后,程序可以继续调用SetViewPortOrgEx,SetViewportExtEx和SetWindowExtEx函数来自由设置坐标系的原点,罗辑单位和坐标的正方向等所有参数,在其他映射方式下的时候,不能使用这3个设置函数,这时任何对它们的调用都会被忽略.---恢复内容结束---