📄 mygiftpiano.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 + -