哈哈,新板块,这么多兄弟来这里冒过泡,看来我是来迟了。
     写点东西大家分享分享,首先声明,我编程很菜,写出来的东西有点像我们专业-土木,又土又木!
    这不是什么高明的文章,可我找这方面的资料也很久了,却也是不多见。我曾在DFCG见过springkang翻译的一篇<<如何在自己的代码中播放XM音乐>>,不过那是C++的,而且要用很多附加工具,比如要用Table Extractor抓取C++格式的XM内容,这样实现起来有点不方便。我在这里介绍一种相对比较方便的实现方法,可以在资源中直接使用xm文件,编译语言就不用说了,肯定是汇编。
    在介绍方法之前,我想介绍一个XM播放支持库,叫mfmplayer.lib,是个叫Lise_Grim的老外写的,大家可以用Google找到,如果去主页,记得要用国外的代理,不然你上不去,更别说下载了。不过这个mfmplayer.lib存在一些问题,我的汇编环境变量设置在了系统变量中,如果哪位也是和我一样的设置,那就请先做一件事,UltraEdit打开mfmplayer.lib,查找\masm32\lib\,把后面的*.lib移到\masm32\lib\所在的地址,后面部分用00填充,我修改过,一共有三个。如果哪位哥们找不到这个mfmplayer.lib,或者懒得去修改,可以下载附件里的(我修改好了)。修改完了以后,把mfmplayer.lib复制到masm32\lib下,当然还有一个mfmplayer.inc复制到masm32\include下面。完成后,就可开始写个播放XM的注册机了(当然,这个mfmplayer.lib不是仅仅可以用在注册机上)。
  
   使用mfmplayer.lib播放XM音乐,先熟悉它最主要的函数mfmPlay。我们可以调用这个函数来播放,也可以用它来停止播放。原型如下:
  
   mfmPlay  PROTO :DWORD
   
   只有一个参数,当dword为xm资源文件在内存的偏移值是,开始加载模块并播放,当dword为0时,停止播放并释放模块。
   mfmplayer.lib里还有另外两个函数,mfmGetPos和mfmPause,用来获取播放位置和暂停,我就不说了,大家也可以参考mfmplayer.inc里说明,我孤陋寡闻,不知道那是哪国文字,有点像英语,内容不多,凑合能看懂。
   废话一大堆,还是放段代码上来大家看看,里面还有滚动字幕的实现方法,我注释了很多地方,希望大家看了代码,立刻就能明白。
   小弟我大胆,在鲁班门前耍大斧,让各位见笑了。
;-----------------------------------------------------------------------------------
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>    在注册机里使用xm产生背景音乐的例子     >>
;>>            编写: qfejj                   >>
;>>           Email :qfejj@163.com           >>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.586
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include kernel32.inc
include gdi32.inc
include user32.inc
include mfmplayer.inc       ;xm播放支持

includelib user32.lib
includelib kernel32.lib
includelib gdi32.lib
includelib user32.lib
includelib mfmplayer.lib   ;xm播放支持库
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
IDD_MAINDLG             equ 1000
IDC_EDT1                equ 1003
IDC_EDT2                equ 1004
IDM_MUSIC               equ 50      ;声音资源
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Windowproc  proto :HWND,:UINT,:WPARAM,:LPARAM
GetRegistKey proto

Color macro Red,Green,Blue                                    ;宏,方便后面颜色设置
      xor eax,eax
      mov ah,Blue
      shl eax,8
      mov ah,Green
      mov al,Red  
endm

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data
String db 'Keygen Template with XM Music ',0dh,0ah
       db '             Designed by qfejj',0dh,0ah
       db 'Contact Email: qfejj@163.com  ',0dh,0ah 
       db ' ==========================  ',0dh,0ah,0   
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>    
.data?
hInstance       HINSTANCE       ?
hWnd            HINSTANCE       ?
NameBuffer      db 32 dup(?)
;音乐
nMusicSize      DWORD           ? 
pMusic          LPVOID          ?
;滚动字幕
hDc    DWORD    ?
hMemoryDc1  DWORD    ?
hMemoryDc2  DWORD    ?
hBrush    DWORD    ?
TextOutX  DWORD    ?
TextOutY  DWORD    ?
TextOutCY  DWORD    ?
LogFont    LOGFONT    <?>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code

start:
  invoke GetModuleHandle,0
  mov hInstance,eax

  invoke DialogBoxParam,hInstance,IDD_MAINDLG,0,offset Windowproc,0

  invoke ExitProcess,0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Windowproc PROC hWin:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL  hBitMapMDc:HDC
LOCAL  ps:PAINTSTRUCT
LOCAL  rect:RECT
LOCAL  TextSizeCX:dword
LOCAL  TextSizeCY:dword
  mov eax,uMsg
.if  eax == WM_PAINT
  invoke BeginPaint,hWin,addr ps
  mov  hDc,eax
  Color 0,0,0
  invoke BitBlt,hDc,0h,0h,100h,40h,hMemoryDc1,0,0,eax  ;将全黑位图从设备场景hMemoryDc1复制到hDc
  invoke EndPaint,hWin,addr ps
.elseif  eax == WM_INITDIALOG
;----------------------------------------------------------  ;==加载音乐,播放==
  push esi 
  invoke FindResource,hInstance,IDM_MUSIC,RT_RCDATA    ;在模块中查找指定的资源,这里是xm文件
  push eax 
  invoke SizeofResource,hInstance,eax 
  mov nMusicSize, eax 
  pop eax 
  invoke LoadResource,hInstance,eax 
  invoke LockResource,eax 
  mov esi,eax 
  mov eax,nMusicSize 
  add eax,sizeof nMusicSize 
  invoke GlobalAlloc,GPTR,eax 
  mov pMusic,eax 
  mov ecx,nMusicSize 
  mov dword ptr[eax],ecx 
  add eax,sizeof nMusicSize 
  mov edi,eax 
  rep movsb 
  pop esi 
  invoke mfmPlay,pMusic                                ;mfmPlay.lib中播放XM的函数
  
;----------------------------------------------------------- ;==实现滚动字幕==
  invoke  SetTimer,hWin,200h,45h,NULL
  invoke  GetDC,hWin
  mov  hDc,eax
  invoke  CreateCompatibleDC,hDc                       ;创建作为大背景的内存设备环境
  mov  hMemoryDc1,eax
  invoke  CreateCompatibleBitmap,hDc,100h,40h          ;创建位图,以供内存设备环境调用作大背景
  mov  hBitMapMDc,eax
  invoke  SelectObject,hMemoryDc1,hBitMapMDc           ;选入刚创建的位图到内存设备环境
  Color   0,0,0                                        ;设置画刷的颜色
  invoke  CreateSolidBrush,eax
  mov  hBrush,eax
  mov  rect.top,0h                                  ;设置矩形大小
  mov  rect.left,0h
  mov  rect.right,100h
  mov  rect.bottom,100h
  invoke  FillRect,hMemoryDc1,addr rect,hBrush         ;用画刷以矩形大小填充内大背景
  invoke  DeleteObject,hBrush
  invoke  CreateCompatibleDC,hDc                       ;创建一个带文字的内存设备
  mov  hMemoryDc2,eax
  Color   255,0,0                                      ;设置字体颜色
  invoke  SetTextColor,hMemoryDc2,eax
  invoke  SetBkMode,hMemoryDc2,TRANSPARENT             ;指定空隙的填充方式-TRANSPARENT-透明处理
  invoke  CreateFontIndirect,addr LogFont              ;创建可以被选入的文字
  invoke  SelectObject,hMemoryDc2,eax
  invoke  CreateCompatibleBitmap,hDc,100h,80h          ;可显示的文字范围
  invoke  SelectObject,hMemoryDc2,eax
  Color   0,0,0                                        ;@1--设置画刷的颜色
  invoke  CreateSolidBrush,eax
  mov  hBrush,eax
  mov  rect.top,0h                                  ;设置矩形大小
  mov  rect.left,0h
  mov  rect.right,100h
  mov  rect.bottom,100h
  invoke  FillRect,hMemoryDc2,addr rect,hBrush         ;填充文字背景,单色时,从@1到这里的代码可以不用
  invoke  DeleteObject,hBrush
  mov  TextOutX,22h
  mov  TextOutY,30h
  lea  esi,String
  mov  al,byte ptr [esi]
  .while  al
    .if  al == 0dh
      add  TextOutY,10h                  ;设置行间距
      mov  TextOutX,22h                  ;换行
      add  esi,2h
    .else
      invoke  GetTextExtentPoint32,hMemoryDc2,esi,1,addr TextSizeCX 
      invoke  TextOut,hMemoryDc2,TextOutX,TextOutY,esi,1h
      mov  eax,TextSizeCX
      add  TextOutX,eax
      inc  esi
    .endif
    mov  al,byte ptr [esi]
  .endw
  invoke  ReleaseDC,hWin,hDc
  
.elseif  eax == WM_TIMER
  invoke  GetDC,hWin
  mov  hDc,eax
  invoke  BitBlt,hMemoryDc1,0h,8h,100h,40h,hMemoryDc2,0,TextOutCY,0cc0020h
  inc  TextOutCY
  .if  TextOutCY == 70h
    mov  TextOutCY,0
  .endif
  invoke  BitBlt,hDc,0h,0h,100h,38h,hMemoryDc1,0,0,0cc0020h    
  invoke  ReleaseDC,hWin,hDc
.elseif eax == WM_CLOSE
        invoke EndDialog,hWin,0
        invoke mfmPlay,0                                      ;停止音乐的播放
  invoke GlobalFree, pMusic                             ;释放背景音乐使用的内存
.elseif eax == WM_COMMAND
  mov eax,wParam
  .if eax ==IDOK
      push hWin
      pop hWnd      
      invoke GetRegistKey                               ;自定义算码函数
  .endif
.else
  mov eax,0
  ret
.endif
mov eax,1
ret
    
Windowproc endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
GetRegistKey proc
        invoke GetDlgItemText,hWnd,IDC_EDT1,offset NameBuffer,sizeof NameBuffer
        invoke SetDlgItemText,hWnd,IDC_EDT2,addr NameBuffer  
  ret

GetRegistKey endp
end start

;---------------------------------------------------------------------------------
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>       keygen.rc       >>>>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define MANIFEST 24
#define IDD_MAINDLG 1000
#define IDOK 1
#define IDC_EDT1 1003
#define IDC_EDT2 1004
#define IDC_STC1 1005
#define IDC_STC2 1006
#define IDC_GRP1 1007
#define IDM_MUSIC 50
IDD_MAINDLG DIALOGEX 4,4,145,112
CAPTION "Kegen for program"
FONT 10,"宋体"
STYLE 0x10CA0880
EXSTYLE 0x00000001
BEGIN
  CONTROL "计算",IDOK,"Button",0x50010000,52,93,41,15,0x00000000
  CONTROL "",IDC_EDT1,"Edit",0x50010000,46,49,87,12,0x00000200
  CONTROL "",IDC_EDT2,"Edit",0x50010800,46,67,87,12,0x00000200
  CONTROL "用户名:",IDC_STC1,"Static",0x50000201,13,49,30,12,0x00000000
  CONTROL "注册码:",IDC_STC2,"Static",0x50000201,13,69,30,12,0x00000000
  CONTROL "",IDC_GRP1,"Button",0x50000007,7,40,132,47,0x00000000
END
1008 ICON DISCARDABLE "ccg.ico"
IDM_MUSIC RCDATA DISCARDABLE "keygen.xm"             ;自己找一个xm文件换上就可以了

;---------------------------------------------------------------------------------

【版权声明】 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!

附件:mfmplayer.rar