⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mygiftpiano.asm

📁 对这个程序的源代码做了详细的说明。因此它可以做为学习windows消息体制的范例
💻 ASM
字号:
; MyGiftVisulPiano
; Ver 1.0.0.0
; 版权所有(C) 谷穗, 2004
; 最后修改: 2004.12.7.(农历10.26)
.386
.model flat,stdcall
option casemap:none

WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc
include \masm32\include\winmm.inc

includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\winmm.lib



.data
ClassName db "SimpleWinClass",0
AppName  db "MyGiftPiano 1.0",0
szText   db "BestGiftBestFriend:MyGiftPiano,帮助请按ESC键!",0h
szCaption	db	'祝鹏娟生日快乐!',0
szText2		db	'数字1234567对应1个音阶的七个音.用abcde控制音阶的声高.qwrty为半音,更多信息请看同目录下的readme.txt文件!',0
.data?
hInstance HINSTANCE ?
hdc HDC ?
midiFlag BYTE ?
midiPu DWORD ?	;MIDI消息,四个字节,处理用户按键时会用相应的信息填充进去
				;再把此消息发送到消息队列中去,这样就把用户的按键转化为了相应的声音
midiYu DWORD ?
midiPlayFlag BYTE ?



.code
start:
	;得到实例(或叫应用程序)句柄.放入eax中
	invoke GetModuleHandle, NULL
	mov    hInstance,eax
	;调用WinMain主过程
	invoke WinMain, hInstance,NULL,NULL,SW_SHOWDEFAULT
	;结束窗口程序
	invoke ExitProcess,eax      

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
	LOCAL wc:WNDCLASSEX
	LOCAL msg:MSG
	LOCAL hwnd:HWND
	mov   wc.cbSize,SIZEOF WNDCLASSEX
	mov   wc.style, CS_HREDRAW or CS_VREDRAW
	mov   wc.lpfnWndProc, OFFSET WndProc
	mov   wc.cbClsExtra,NULL
	mov   wc.cbWndExtra,NULL
	push  hInst
	pop   wc.hInstance
	mov   wc.hbrBackground,COLOR_WINDOW+1
	mov   wc.lpszMenuName,NULL
	mov   wc.lpszClassName,OFFSET ClassName
	invoke LoadIcon,NULL,IDI_APPLICATION
	mov   wc.hIcon,eax
	mov   wc.hIconSm,eax
	invoke LoadCursor,NULL,IDC_ARROW
	mov   wc.hCursor,eax
	;注册窗口类
	invoke RegisterClassEx, addr wc
	;建立窗口.
	INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
           WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
           CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
           hInst,NULL
	mov   hwnd,eax
	;显示窗口
	INVOKE ShowWindow, hwnd,SW_SHOWNORMAL
	;刷新窗口客户区.
	INVOKE UpdateWindow, hwnd
	;打开一个MIDI输出设备.(Musical Instrument Digital Interface),
	;hdc为设备句柄
      invoke midiOutOpen,ADDR hdc,-1,NULL,NULL,NULL
      mov   midiYu,0h
      mov   midiPlayFlag,1h
	.WHILE TRUE
				;取得、转换(如:将扫描码转换成ASCII码)、分派消息.
				;这三者组成一个消息循环,不断循环的来处理WINDOWS消息
                INVOKE GetMessage, ADDR msg,NULL,0,0
				;eax是用来控制当消息队列为空时把程序的控制权交给程序,
				;如果不这样将会导致窗口会陷入无穷无尽的消息循环当中的!!
                .BREAK .IF (!eax)
                INVOKE TranslateMessage, ADDR msg
                INVOKE DispatchMessage, ADDR msg
	.ENDW
	mov     eax,msg.wParam
	ret
WinMain endp
;窗口过程.处理消息的.HWND为windows回调时基于的窗口的窗口句柄.
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
		local	 @stPs:PAINTSTRUCT
		local	 @stRect:RECT
		local	 @hDc  
            local   @playf:WORD

	.IF uMsg==WM_DESTROY
             invoke midiOutClose,hdc
		    invoke PostQuitMessage,NULL
                    
      .ELSEIF uMsg ==WM_PAINT
			;发送WM_ERASEBKGND消息来擦除背景.
			;WM_ERASEBKGND消息是用窗口类结构中的hbrBackground刷子来绘画窗口背景
			invoke	BeginPaint,hWnd,addr @stPs
			mov	      @hDc,eax
			invoke	GetClientRect,hWnd,addr @stRect
			invoke	DrawText,@hDc,addr szText,-1,\
				addr @stRect,\
				DT_SINGLELINE or DT_CENTER or DT_VCENTER
			invoke	EndPaint,hWnd,addr @stPs
      .ELSEIF uMsg==WM_CHAR
      mov @playf,0h
      push wParam
      pop midiPu
;===============ESC键的功能: 弹出一个消息框================
          .if midiPu==WM_DEVMODECHANGE                  ;1bh
          ; invoke midiOutClose,hdc

	    	invoke	MessageBox,NULL,offset szText2,offset szCaption,MB_OK
          .ENDIF
;----------------------------------------

		;用abcde控制音阶的声高
        .if midiPu==61h;按下a
        mov midiYu,-24
        .elseif midiPu==62h;按下b
        mov midiYu,-12
        .elseif midiPu==63h;按下c
        mov midiYu,0
        .elseif midiPu==64h;按下d
        mov midiYu,12
        .elseif midiPu==65h;按下f
        mov midiYu,24
      
        ;===============全音============================
        .elseif midiPu==31h;按下1
        mov midiPu,3ch
        mov @playf,1
        .elseif midiPu==32h
        mov midiPu,3eh
        mov @playf,1
        .elseif midiPu==33h
        mov midiPu,40h
        mov @playf,1
        .elseif midiPu==34h
        mov midiPu,41h
        mov @playf,1
        .elseif midiPu==35h
        mov midiPu,43h
        mov @playf,1
        .elseif midiPu==36h
        mov midiPu,45h
        mov @playf,1
        .elseif midiPu==37h
        mov midiPu,47h
        mov @playf,1
        ;================半音===========================
         .elseif  midiPu==71h;按下q
         mov midiPu,3dh
         mov @playf,1
         .elseif  midiPu==77h;按下w
         mov midiPu,3fh
         mov @playf,1
         .elseif  midiPu==72h;按下r
         mov midiPu,42h
         mov @playf,1
         .elseif  midiPu==74h;按下t
         mov midiPu,44h
         mov @playf,1
         .elseif  midiPu==79h;按下y
         mov midiPu,46h
         mov @playf,1
         .endif
        ;----------处理半音-------------------
          .if @playf==1
            mov eax,midiYu
            add midiPu,eax
            mov cl,8
            shl midiPu,cl
            and midiPu,0ff00h
            add midiPu,680090h
           .if midiPlayFlag==1h
            ;================调用声卡的代码======================      
        
            invoke midiOutShortMsg,hdc,midiPu
            mov  midiPlayFlag,0h
            ;-------------------声卡代码结束------------------------
            .endif
            .endif
	.ELSEIF uMsg==WM_KEYUP
      	    mov midiPlayFlag,1h
	.ELSE
		invoke DefWindowProc,hWnd,uMsg,wParam,lParam
		ret
	.ENDIF
	xor    eax,eax
	ret
WndProc endp
end start

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -