在本文中,将探讨如何使用C++语言和直接访问核心FLAT SDK API来开发一个轻量级的MIDI播放器。这个项目的目标是创建一个仅36KB大小的独立可执行文件,这需要尽可能地减少运行时库的使用,并且采用直接调用核心API的方法。
这个项目由Borje Hagsten编写,最初是用BASIC语言实现的,但后来也被翻译成了WinDev p-code。这个GUI提供了一个完整的MIDI界面,用户可以使用鼠标或PC键盘来演奏选定的乐器。
用户可以通过按下F1键来显示帮助信息。这个项目是用最新的C++Visual Studio 2017社区免费版完成的。为了增加趣味性,可以通过编辑Main.cpp文件末尾的代码行来启用额外的“皮肤”功能。
//if (skInitEngine (L"Reader.sks", L"")) { // these 2 lines enable or disable
// if (skSkinWindow(gP.hMain, (WCHAR*) SYSTOOLTIP)) { // the use of the WinLIFT skin engine.
// Show the main window
ShowWindow(gP.hMain, nCmdShow);
UpdateWindow(gP.hMain);
while
(GetMessage(&msg, NULL,
0
,
0
)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// }
// }
使用WinLIFT的魔力,整个GUI将会变成这样:
如果想大幅度减少64位代码的大小,可以遵循以下几个步骤:
以下是如何使用显式链接到MSVCRT来实现最终粒度的示例:
#define long_proc typedef long (__stdcall *zProc)
#define void_proc typedef void (__stdcall *zProc)
#define double_proc typedef double (__stdcall *zProc)
#define M_LOG2E 1.44269504088896340736
HMODULE MSVCRT() {
static
HMODULE hModule;
if
(hModule ==
0
) { hModule = LoadLibrary(L
"
MSVCRT"
); }
return
hModule;
}
double
log2(IN
double
X) {
double
l2 =
0
;
HMODULE hModule = MSVCRT();
if
(hModule) {
double_proc (
double
);
zProc hProc = (zProc) GetProcAddress(hModule,
"
log"
);
if
(hProc) { l2 = hProc(X) * M_LOG2E; }
}
return
l2;
}
void
RandoMize(IN DWORD seed) {
HMODULE hModule = MSVCRT();
if
(hModule) {
void_proc (DWORD);
zProc hProc = (zProc) GetProcAddress(hModule,
"
srand"
);
if
(hProc) { hProc(seed); }
}
}
long
Rand() {
long
nRand =
0
;
HMODULE hModule = MSVCRT();
if
(hModule) {
long_proc ();
zProc hProc = (zProc) GetProcAddress(hModule,
"
rand"
);
if
(hProc) { nRand = hProc(); }
}
return
nRand;
}
size_t rnd(IN
long
nMin, IN
long
nMax) {
//
QWORD
double
dblRange = nMax - nMin;
double
dblMaxFactor = dblRange / RAND_MAX;
double
dblRandomNumber = (
double
) Rand();
return
(size_t) (nMin + dblMaxFactor * dblRandomNumber);
}