WM_PIANT消息与窗口重画

Windows窗口消息分类及重画消息发送方法
本文介绍了Windows窗口消息相关知识。消息分为队列化和非队列化,队列化消息由Windows放入程序消息队列,非队列化消息直接送给窗口消息处理程序。还列举了队列化和非队列化消息的常见类型,并介绍了向Windows发送WM_PAINT消息请求重画的几种方法。
Windows给窗口发送消息,这意味著Windows调用窗口消息处理程序。但是,Windows程序也有一个消息循环,它调用GetMessage从消息队列中取出消息,并且调用DispatchMessage将消息发送给窗口消息处理程序。 那么,Windows程序是依次等待消息(类似于普通程序中相同的键盘输入),然后将消息送到某地方去的吗?或者,它是直接从程序外面接收消息的吗?实际上,两种情况都存在。 消息能够被分为「队列化的」和「非队列化的」。队列化的消息是由Windows放入程序消息队列中的。在程序的消息循环中,重新传回并分配给窗口消息处理程序。非队列化的消息在Windows调用窗口时直接送给窗口消息处理程序。也就是说,队列化的消息被「发送」给消息队列,而非队列化的消息则「发送」给窗口消息处理程序。任何情况下,窗口消息处理程序都将获得窗口所有的消息--包括队列化的和非队列化的。窗口消息处理程序是窗口的「消息中心」。 队列化消息基本上是使用者输入的结果,以击键(如WM_KEYDOWN和WM_KEYUP消息)、击键产生的字(WM_CHAR)、鼠标移动(WM_MOUSEMOVE)和鼠标按钮(WM_LBUTTONDOWN)的形式给出。队列化消息还包含时钟消息(WM_TIMER)、更新消息(WM_PAINT)和退出消息(WM_QUIT)。 非队列化消息则是其他消息。在许多情况下,非队列化消息来自调用特定的Windows函数。例如,当WinMain调用CreateWindow时,Windows将建立窗口并在处理中给窗口消息处理程序发送一个WM_CREATE消息。当WinMain调用ShowWindow时,Windows将给窗口消息处理程序发送WM_SIZE和WM_SHOWWINDOW消息。当WinMain调用UpdateWindow时,Windows将给窗口消息处理程序发送WM_PAINT消息。键盘或鼠标输入时发出的队列化消息信号,也能在非队列化消息中出现。例如,用键盘或鼠标选择了一个菜单项时,键盘或鼠标消息就是队列化的,而说明菜单项已选中的WM_COMMAND消息则可能就是非队列化的。 向WINDOWS发送WM_PAINT消息请求重画的几个方法 1 用PostMessage(),SendMessage()函数发送WM_PAINT消息 使用以上两函数发送WM_PAINT消息,能将WM_PAINT消息发送到WINDOWS程序消息队列中,当WINDOWS将WM_PAINT消息发送给具体的消息处理函数时,如果窗口的无效区域为空则WINDOWS将不理睬该消息。若存在无效区域,则调用窗口处理函数处理。 2 Invalidate(),Invalidaterect(), InvalidateRgn(); 以上函数将窗口的特定区域标定为无效,当WINDOWS检测到窗口中存在无效区域时将向消息队列发送WM_PAINT 消息。 3 UpdateWindow() 该函数调用后WINDOWS将向窗口发送一个非队列化的WM_PAINT消息,它不经过消息循环而直接发送给了窗口消息处理函数。如果窗口无效区域不存在,WINDOWS将不理睬该消息。
SHOW MACRO B MOV DX,OFFSET B MOV AH,09H INT 21H ENDM ;信息显示宏定义 PUSH_ALL MACRO PUSH AX PUSH BX PUSH CX PUSH DX ENDM ;堆栈压入宏定义 POP_ALL MACRO POP DX POP CX POP BX POP AX ENDM ;堆栈弹出宏定义 PIANT MACRO START_X,START_Y,END_X,END_Y,COLOR LOCAL DRAW ;使用条件:START_X<END_X,START_Y<END_Y PUSH_ALL ;初始化 MOV AH,0CH ;写图形象素 MOV AL,COLOR ;设置颜色 MOV BH,0 ;选用页号0 MOV CX,START_X ;图像列起始点 MOV DX,START_Y ;图像行起始点 DRAW: INT 10H INC CX ;画横线 CMP CX,END_X ;比较列是否画完 JNE DRAW ;没画完则继续画 INC DX ;若画完,列数加一 MOV CX, START_X ;另一行的起始点 CMP DX,END_Y ;比较列是否画完 JNE DRAW ;未完继续画 POP_ALL ENDM ;绘制填充的矩形 DRAWSQRE MACRO START_X,START_Y,END_X,END_Y,COLOR LOCAL UP,DOWN,LEFT,RIGHT PUSH_ALL PUSH SI MOV AH,0CH MOV AL,COLOR MOV BH,0 MOV CX,START_X MOV DX,START_Y UP: INT 10H ;画上边框 INC CX CMP CX,END_X JNE UP RIGHT: INT 10H ;画右边框 INC DX CMP DX,END_Y JNE RIGHT DOWN: INT 10H ;画下边框 DEC CX CMP CX,START_X JNE DOWN LEFT: INT 10H ;画右边框 DEC DX CMP DX, START_Y JNE LEFT POP SI POP_ALL ENDM ;画不填充的矩形 DSEG SEGMENT ;定义数据段 MENU DB '--------------FRIENDLY-TIPS-------------------',0DH,0AH DB '1.SHOW THE[NAME], PRESS "A" key. ',0DH,0AH DB '2.SHOW THE[NUMBER], PRESS "B" key. ',0DH,0AH DB '3.AUTO, PRESS "C" key. ',0DH,0AH DB '4.TO EXIT, PRESS "ESC" key. ',0AH,0DH N=$-OFFSET MENU XINGMING DB ' 00000000000000000000000000000000000000000000000000000000000000000 ',0DH,0AH DB ' 0 * 0 ',0DH,0AH DB ' 0 ******* * * * ********* * 0 ',0DH,0AH DB ' 0 * * * *********** * * * * 0 ',0DH,0AH DB ' 0 **************** * * * * * * 0 ',0DH,0AH DB ' 0 * * * ******* ********** * 0 ',0DH,0AH DB ' 0 * * * * * * * 0 ',0DH,0AH DB ' 0 * *** * * ********* * * * * 0 ',0DH,0AH DB ' 0 * * * * * * * * 0 ',0DH,0AH DB ' 0 * * * * * * * * * * 0 ',0DH,0AH DB ' 0 * * * * * * * * * * 0 ',0DH,0AH DB ' 0 * * * * * * * * * * 0 ',0DH,0AH DB ' 0 ********* * * ********* * 0 ',0DH,0AH DB ' 0 0 ',0DH,0AH DB ' 00000000000000000000000000000000000000000000000000000000000000000 ',0DH,0AH;显示姓名信息 XINGMING_LEN=$-OFFSET XINGMING ;姓名信息字符长度 NUM DB ' 00000000000000000000000000000000000000000000000000000000000000000 ',0DH,0AH DB ' 0 0 ',0DH,0AH DB ' 0 ***** ****** ***** ****** ****** ****** ****** * * * 0 ',0DH,0AH DB ' 0 * * * * * * * * * * * * * * 0 ',0DH,0AH DB ' 0 * * * * * * * * * * * * * * 0 ',0DH,0AH DB ' 0 ***** * * ***** * * * * ****** * * ****** 0 ',0DH,0AH DB ' 0 * * * * * * * * * * * * 0 ',0DH,0AH DB ' 0 * * * * * * * * * * * * 0 ',0DH,0AH DB ' 0 ***** ****** ***** ****** ****** ****** * * * 0 ',0DH,0AH DB ' 0 0 ',0DH,0AH DB ' 00000000000000000000000000000000000000000000000000000000000000000 ',0DH,0AH;显示学号信息 NUM_LEN=$-OFFSET NUM ;学号信息字符长度,使学号能够出现在矩形边框内 COLORB DB 5FH,3FH,0EH,17H,72H,0FH,04H,05H,0BH ;定义颜色属性,出现六种颜色 COLORE LABEL BYTE ;最后一个颜色地址指针给COLORE DEFINE DW 262,294,330,349,392,440,494,525 MESSAGE DB 'Play the music!','$',0AH,0DH INSTRUCT DB ' Welcome to the electronic organ ',0AH,0DH DB ' 1.Use 1~8keys to play ',0AH,0DH DB ' 2.SPACE to replay ',0AH,0DH DB ' 3.ENTER to exit ',0AH,0DH M=$-OFFSET INSTRUCT RECORDER DW 100 DUP(?) MUS_FRQ1 DW 262,294,330,262 DW 262,294,330,262 DW 330,349,392 DW 330,349,392 DW 392,440,392,349,330,262 DW 392,440,392,349,330,262 DW 294,392,262 DW 294,392,262,-1 MUS_TIME1 DW 80,80,80,160 DW 80,80,80,160 DW 80,80,160 DW 80,80,160 DW 50,50,50,50,50,100 DW 50,50,50,50,50,100 DW 80,80,160 DW 80,80,160 MUS_FRQ2 DW 262,294,330,262 DW 262,294,330,262 DW 330,349,392 DW 330,349,392 DW 392,440,392,349,330,262 DW 392,440,392,349,330,262 DW 294,392,262 DW 294,392,262,-1 MUS_TIME2 DW 80,80,80,160 DW 80,80,80,160 DW 80,80,160 DW 80,80,160 DW 50,50,50,50,50,100 DW 50,50,50,50,50,100 DW 80,80,160 DW 80,80,160 MUS_FRQ3 DW 262,294,330,262 DW 262,294,330,262 DW 330,349,392 DW 330,349,392 DW 392,440,392,349,330,262 DW 392,440,392,349,330,262 DW 294,392,262 DW 294,392,262,-1 MUS_TIME3 DW 80,80,80,160 DW 80,80,80,160 DW 80,80,160 DW 80,80,160 DW 50,50,50,50,50,100 DW 50,50,50,50,50,100 DW 80,80,160 DW 80,80,160 DSEG ENDS ;数据段结束 CSEG SEGMENT ;定义代码段 ASSUME CS: CSEG,DS:DSEG START: MOV AX,DSEG MOV DS,AX MOV ES,AX ;ES指向数据段 CALL CLEAR ;调用清屏子程序 MOV AH,00H ;设置显示方式 MOV AL,03H ;80*25彩色文本模式 INT 10H ;显示器功能调用 MOV AH,0BH ;设置CGA调色板 MOV BH,0 ;设定颜色 MOV BL,00H ;背景色黑色 INT 10H ;显示功能调用 LEA BP,MENU ;把MENU的偏移地址给BP MOV AH,13H ;显示字符串 MOV AL,01 ;光标跟随移动 MOV CX,N ;显示字符串长度 MOV BL,2FH ;菜单颜色设为绿底白字 MOV BH,0 ;页号 MOV DL,0 ;起始列 MOV DH,0 ;起始行 INT 10H ;显示器功能调用 POINT: MOV DI,OFFSET COLORB-1 ;颜色指针初值 POINT1: INC DI CMP DI,OFFSET COLORE JNZ POINT2 MOV DI,OFFSET COLORB POINT2: MOV BL,[DI] ;取颜色 MOV AH,0 ;读取键值 INT 16H ;键盘功能调用 CMP AL,61H JZ NAM ;若按下A键(即ASSIC码值‘a’相等),则转移至NAM子程序 CMP AL,62H JZ NUMBER ;若按下B键,则转移至NUMBER子程序 CMP AL,63H JZ AUTO ;若按下C键,则转移至AUTO子程序 CMP AL,64H CMP AL,1BH JZ OVER ;若按键值为ESC,则转移至OVER子程序,即退出 JMP POINT ;若按键值不为ESC,则转移至POINT子程序 OVER: MOV AH,4CH INT 21H ;程序终止 NAM: CALL FASAN ;调用FASAN程序段 MOV SI,OFFSET XINGMING ;取XINGMING地址送入SI MOV CX,XINGMING_LEN ;取XINGMING字符长度送入CX MOV DH,7 ;运行屏幕显示的行号 MOV DL,0 ;运行屏幕显示的列号 CALL ECH ;调用ECH子程序 CALL MUSIC1 ;调用MUSIC1子程序 JMP POINT1 ;转移至POINT1子程序 MUSIC1 PROC ;MUSIC1过程定义 SHOW MESSAGE ;显示MESSAGE缓冲器中的字符串 LEA SI, MUS_FRQ1 LEA BP,DS: MUS_TIME1 FREQ1: MOV CX, [SI] ;将第一个元素给CX CMP CX,-1 JE END_MUS1 MOV BX, DS: [BP] ;将时间表第一个元素给BX CALL SOUND ADD SI,2 ADD BP,2 JMP FREQ1 END_MUS1: RET MUSIC1 ENDP NUMBER: CALL SHUNSHIZHEN ;调用SHUNSHIZHEN子程序 MOV SI,OFFSET NUM ;取NUM地址送入SI MOV CX,NUM_LEN ;将NUM字符长度送入CX MOV DH,9 ;运行屏幕显示的行号 MOV DL,0 ;运行屏幕显示的列号 CALL ECH ;调用ECH子程序 CALL MUSIC2 ;调用MUSIC2子程序 JMP POINT1 ;转移至POINT1子程序 MUSIC2 PROC ;MUSIC2过程定义 SHOW MESSAGE ;显示MESSAGE缓冲器中的字符串 LEA SI, MUS_FRQ2 LEA BP,DS: MUS_TIME2 FREQ2: MOV CX, [SI] ;将第一个元素给CX CMP CX,-1 JE END_MUS2 MOV BX, DS: [BP] ;将时间表第一个元素给BX CALL SOUND ADD SI,2 ADD BP,2 JMP FREQ2 END_MUS2: RET MUSIC2 ENDP ;MUSIC3过程定义结束 AUTO: CALL CLEAR ;调用CLEAR子程序 MOV BL,[DI] MOV SI,OFFSET XINGMING ;取XINGMING地址送入SI MOV CX,XINGMING_LEN ;取XINGMING字符长度送入CX MOV DH,7 ;运行屏幕显示的行号 MOV DL,0 ;运行屏幕显示的列号 CALL ECH ;调用ECH带延时显示子程序 CALL SHUNSHIZHEN ;调用顺时针消除子程序 CALL DELAY5 ;调用DELAY5延时子程序 INC DI ;DI自加 MOV BL,[DI] MOV SI,OFFSET NUM ;取NUM地址送入SI MOV CX,NUM_LEN ;取NUM字符长度送入CX MOV DH,7 ;运行屏幕显示的行号 MOV DL,0 ;运行屏幕显示的列号 CALL ECH ;调用ECH带延时显示子程序 CALL FASAN ;调用发散子程序 CALL DELAY5 ;调用DELAY5延时子程序 MUSIC3 PROC ;MUSIC3过程定义 SHOW MESSAGE ;显示MESSAGE缓冲器中的字符串 LEA SI, MUS_FRQ3 LEA BP,DS: MUS_TIME3 FREQ3: MOV CX, [SI] ;将第一个元素给DI CMP CX,-1 JE END_MUS3 MOV BX, DS: [BP] ;将时间表第一个元素给BX CALL SOUND ADD SI,2 ADD BP,2 JMP FREQ3 END_MUS3: RET MUSIC3 ENDP ;MUSIC3过程定义结束 ;000000000000000000000 ;000000声音子程序00000 ;000000000000000000000 SOUND PROC PUSH_ALL PUSH DI MOV AL,10110110B OUT 43H,AL ;通过AL将控制字写入43H端口 MOV AX,34DCH MOV DX,12H DIV CX OUT 42H,AL MOV AL,AH OUT 42H,AL IN AL,61H OR AL,3 ;把PB0和PB1置1 OUT 61H,AL ;使扬声器发声 WAIT1: MOV CX,02A56H DELAY1: LOOP DELAY1 DEC BX JNZ WAIT1 ;延时 IN AL,61H AND AL,11111100B OUT 61H,AL ;关闭扬声器 POP DI POP_ALL RET SOUND ENDP ;000000000000000000000 ;000000显示子程序00000 ;000000000000000000000 ECH PROC NEAR ;带延时显示子程序 JCXZ ECH2 ;如果字符串长度为零,则转移至ECH2,即结束 MOV BH,0 ;光标所在的页号 MOV AH,2 ;设置光标的位置 INT 10H MOV AL,20H ;AL=字符的ASCII码值(空格) MOV AH,9 ;在光标处写字符及其属性 INT 10H MOV AH,0EH ECH1: MOV AL,[SI] INC SI CMP AL,26H JNE ECH3 ;不等跳转 MOV AL,03H ;将&字符转换为心型字符 ECH3: INT 10H ;逐个显示字符 CALL DELAY4 ;调用延时子程序 LOOP ECH1 ;循环ECH1 ECH2: RET ECH ENDP ;000000000000000000000 ;000000延时子程序00000 ;000000000000000000000 DELAY4 PROC NEAR ;字符输入延时子程序 PUSH CX PUSH BX MOV BX,07H WAIT1: MOV CX,0FFFH WAIT2: LOOP WAIT2 ;若CX不为0,则循环WAIT2 DEC BX ;BX自减 JNZ WAIT1 ;若BX不为0,则转移至WAIT1 POP BX POP CX RET DELAY4 ENDP DELAY5 PROC NEAR ;短延时子程序 PUSH CX PUSH BX MOV BX,100H WAIT3: MOV CX,0FFFH WAIT4: LOOP WAIT4 ;若CX不为0,则循环WAIT4 DEC BX JNZ WAIT3 ;若BX不为0,则转移至WAIT3 POP BX POP CX RET DELAY5 ENDP ;000000000000000000000 ;000000清屏子程序00000 ;000000000000000000000 CLEAR PROC NEAR ;清屏程序 PUSH_ALL MOV CH,0 ;滚动窗口左上角行号 MOV CL,0 ;滚动窗口左上角列号 MOV DH,40 ;滚动窗口右下角行号 MOV DL,80 ;滚动窗口右下角列号 MOV BH,07H ;卷入行属性 MOV AL,0 ;窗口空白 MOV AH,6 ;窗口上滚 INT 10H POP_ALL RET CLEAR ENDP FASAN PROC NEAR ;发散消除子程序 PUSH_ALL ;第1次消除 MOV CH,12 ;滚动窗口左上角行号 MOV CL,25 ;滚动窗口左上角列号 MOV DH,15 ;滚动窗口右下角行号 MOV DL,45 ;滚动窗口右下角列号 MOV BH,07 ;卷入行属性 MOV AL,0 ;窗口空白 MOV AH,06H ;窗口上滚 INT 10H CALL DELAY5 MOV CH,10 ;第2次消除 MOV CL,17 MOV DH,17 MOV DL,57 MOV BH,07 MOV AL,0 MOV AH,7 INT 10H CALL DELAY5 MOV CH,8 ;第3次消除 MOV CL,9 MOV DH,19 MOV DL,68 MOV BH,07 MOV AL,0 MOV AH,6 INT 10H CALL DELAY5 MOV CH,6 ;第4次消除 MOV CL,0 MOV DH,21 MOV DL,80 MOV BH,07 MOV AL,0 MOV AH,6 INT 10H CALL DELAY5 POP_ALL RET FASAN ENDP SHUNSHIZHEN PROC NEAR ;顺时针消除子程序 PUSH_ALL ;第1次消除 MOV CH,6 ;滚动窗口左上角行号 MOV CL,0 ;滚动窗口左上角列号 MOV DH,11 ;滚动窗口右下角行号 MOV DL,50 ;滚动窗口右下角列号 MOV BH,07 ;卷入行属性 MOV AL,0 ;窗口空白 MOV AH,6 ;窗口上滚 INT 10H CALL DELAY5 MOV CH,6 ;第2次消除 MOV CL,51 MOV DH,30 MOV DL,80 MOV BH,07 MOV AL,0 MOV AH,7 INT 10H CALL DELAY5 MOV CH,16 ;第3次消除 MOV CL,0 MOV DH,30 MOV DL,50 MOV BH,07 MOV AL,0 MOV AH,6 INT 10H CALL DELAY5 MOV CH,12 ;第4次消除 MOV CL,0 MOV DH,15 MOV DL,50 MOV BH,07 MOV AL,0 MOV AH,6 INT 10H CALL DELAY5 POP_ALL RET SHUNSHIZHEN ENDP CSEG ENDS END START
最新发布
07-01
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值