在Win32 SDK中使用Lu模块化编译运行库MLu
(Windows XP系统,使用VC 2008演示)
(欢迎访问:http://www.forcal.net/)
演示如何在Windows程序中加入Lu脚本支持,比较快捷的方式是通过MLu使用Lu脚本。图示说明如何在Win32SDK中使用Lu模块化编译运行库MLu。
完整版请参考:http://www.forcal.net/bczl/luc/pwinsdkmlu.doc
以下是基本步骤,未包含相关图片。
1、启动VS 2008(VC++ 2008),点击红色圈出部分创建项目。
2、创建Win32项目,名称为TestMLu,点击“确定”。
3、点击“下一步”。
4、选择“空项目”,点击“完成”。
5、工程生成后如下图所示。
6、在进行下一步之前,先来看看我们要设计的主程序界面,我们将先实现这个界面。
7、实现主程序界面的代码:这些代码没有使用Lu,仅仅实现主程序界面
头文件:TestMLu.h(文件创建方法:先创建一个文本文件,输入以下内容并保存,然后更改文件名为TestMLu.h)
#define IDM_cal_com 10
#define IDM_cal_cal 11
#define IDM_cal_comcal 12
#define IDE_EditCode 30
#define IDE_EditOut 31
(注意:复制到文件中后,最后一条语句后面,请加一个回车,否则容易出现编译错误。下同。)
资源文件:TestMLu.rc(文件创建方法:先创建一个文本文件,输入以下内容并保存,然后更改文件名为TestMLu. rc)
#include "windows.h"
#include "TestMLu.h"
// Menu
mainMenu MENU DISCARDABLE
{
POPUP "计算(&J)"
{
MENUITEM "计算(&J)", IDM_cal_comcal
MENUITEM SEPARATOR
MENUITEM "编译(&B)", IDM_cal_com
MENUITEM "执行(&Z)", IDM_cal_cal
}
}
实现文件:TestMLu.cpp(文件创建方法:先创建一个文本文件,输入以下内容并保存,然后更改文件名为TestMLu.cpp)
#include "windows.h"
#include "TestMLu.h"
////////////////////////////////////// 全局数据
HINSTANCE hInstance; //实例句柄
HWND hwndEditCode,hwndEditOut; //代码窗口和输出窗口
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); //窗口函数说明
//////////////////////////////////////// Windows应用程序入口
int WINAPI WinMain(HINSTANCE hhInstance,HINSTANCE hPrevInst,LPSTR lpszCmdLine,int nCmdShow)
{
HWND hWnd;
MSG Msg ;
WNDCLASS wndclass ;
wchar_t lpszClassName[]=L"classTestMLu";//窗口类名
wchar_t lpszTitle[]= L"TestMLu"; //窗口标题名
hInstance=hhInstance; //记住实例句柄
//窗口类的定义
wndclass.style = 0; //窗口类型
wndclass.lpfnWndProc = WndProc ; //窗口处理函数为WndProc
wndclass.cbClsExtra = 0 ; //窗口类无扩展
wndclass.cbWndExtra = 0 ; //窗口实例无扩展
wndclass.hInstance = hInstance ; //当前实例句柄
wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION) ;//窗口的最小化图标为缺省图标
wndclass.hCursor = LoadCursor( NULL, IDC_ARROW) ;//窗口采用箭头光标
wndclass.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH) ;//窗口背景为白色
wndclass.lpszMenuName = L"mainMenu" ; //窗口菜单
wndclass.lpszClassName = lpszClassName ;//窗口类名
//窗口类注册
if( !RegisterClass( &wndclass)) //如果注册失败则发出警告声音
{
MessageBeep(0) ;
MessageBox(GetFocus(),L"注册失败!",L"TestMLu",MB_OK);
return 0;
}
//创建窗口
hWnd=CreateWindow(lpszClassName, //窗口类名
lpszTitle, //窗口实例的标题名
WS_OVERLAPPEDWINDOW,//窗口的风格
CW_USEDEFAULT,
CW_USEDEFAULT, //窗口左上角坐标为缺省值
CW_USEDEFAULT,
CW_USEDEFAULT, //窗口的高和宽为缺省值
NULL, //此窗口无父窗口
NULL, //此窗口无主菜单
hInstance, //创建此窗口的应用程序的当前句柄
NULL) ; //不使用该值
//显示窗口
ShowWindow( hWnd, SW_SHOWNORMAL) ;
//绘制用户区
UpdateWindow(hWnd);
//消息循环
while( GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage( &Msg) ;
DispatchMessage( &Msg) ;
}
if(!UnregisterClass(lpszClassName,hInstance))// Are We Able To Unregister Class
{
MessageBox(NULL,L"Could Not Unregister Class.",L"TestMLu",MB_OK | MB_ICONINFORMATION);
}
return Msg.wParam; //消息循环结束即程序终止时将信息返回系统
}
//窗口函数
LRESULT CALLBACK WndProc(HWND hWnd,UINT Message,WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_CREATE:
hwndEditCode=CreateWindow(L"EDIT",NULL, //创建代码编辑框;
WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|WS_BORDER|ES_LEFT|ES_MULTILINE|
ES_AUTOHSCROLL|ES_AUTOVSCROLL,
0,0,LOWORD(lParam),HIWORD(lParam/2),hWnd,(HMENU)IDE_EditCode,hInstance,NULL);
hwndEditOut=CreateWindow(L"EDIT",NULL, //创建输出编辑框;
WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|WS_BORDER|ES_LEFT|ES_MULTILINE|
ES_AUTOHSCROLL|ES_AUTOVSCROLL,
0,HIWORD(lParam/2+2),LOWORD(lParam),HIWORD(lParam/2-2),hWnd,(HMENU)IDE_EditOut,hInstance,NULL);
SetWindowText(hwndEditCode,L"//这里是代码窗口,请将Lu代码写在下面\r\n");
SetFocus(hwndEditCode);
break;
case WM_SIZE:
MoveWindow(hwndEditCode,0,0,LOWORD(lParam),HIWORD(lParam/2),true);
MoveWindow(hwndEditOut,0,HIWORD(lParam/2+2),LOWORD(lParam),HIWORD(lParam/2),true);
UpdateWindow(hWnd);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDM_cal_com:
break;
case IDM_cal_cal:
break;
case IDM_cal_comcal:
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0); //调用PostQuitMessage发出WM_QUIT消息
break;
default: //默认时采用系统消息默认处理函数
return DefWindowProc(hWnd,Message,wParam,lParam);
}
return 0;
}
8、将TestMLu.h、TestMLu.rc和TestMLu.cpp三个文件放到文件夹“D:\lu\lu32\TestMLu\TestMLu”。
9、返回VC,点击下图中红色圈出部分“项目->添加现有项”。
10、添加TestMLu.h、TestMLu.rc和TestMLu.cpp三个文件到工程中。
11、新的工程如下图,点击下图中红色圈出部分“生成->生成解决方案”。
12、生成成功。
13、点击下图中红色圈出部分“调试->开始执行(不调试)”。
14、程序界面如下图所示,与我们设想一致。
15、在“TestMLu.cpp”中加入Lu脚本支持的代码,注意红色和青色部分是新加的。
/***********************************************************************
使用MLu的一般步骤:
(1)使用函数InitMLu进行初始化(必须)。
(2)使用函数LoadDll加载需要的Lu扩展库。
(3)使用函数ComModule将字符串源代码编译为模块(必须)。
(4)使用函数ExeModule执行模块,或者使用函数GetFor获取需要的表达式进行计算(必须)。
(5)使用函数SearchKey验证操作数据的类型,然后进行数据传送操作。(本例未使用)
(6)使用函数FreeDll卸载Lu扩展库。
(7)使用函数FreeMLu释放资源(必须)。
***********************************************************************/
#include "windows.h"
#include "TestMLu.h"
//使用Lu脚本必须的头文件
#include "lu32.h"
//隐式加载MLu时,需要使用的导入库文件
#pragma comment( lib, "lu32.lib" )
#pragma comment( lib, "mlu32.lib" )
////////////////////////////////////// 全局数据
HINSTANCE hInstance; //实例句柄
HWND hwndEditCode,hwndEditOut; //代码窗口和输出窗口
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); //窗口函数说明
//友情提示:所有定义的变量和函数,可通过编辑器提供的查找功能查看它在哪里使用
//要加载的Lu扩展动态库
wchar_t AllDllName[]=L"\"dll\\LuSystem32.dll\",\"dll\\LuMath32.dll\",\"dll\\LuOpt32.dll:138413699\",\"dll\\LuIMSL32.dll:dll\\IMSL32.dll\",\"dll\\Lu2D32.dll\",\"dll\\LuWin32.dll\",\"dll\\OpenLuGl32.dll\"";
luVOID nModule=0; //编译模块时所用的起始模块号,一般设为0
void *hModule=NULL; //模块句柄,记住当前编译的模块。本例中,在编译时将销毁以前编译的模块
////////////////////////////////////// MLu使用的函数
//输出动态库信息,该函数注册到Lu,由Lu二级函数调用,输出必要的信息
void _stdcall LuMessage(wchar_t *pch)
{
int nTextLength;
if(!pch) return;
nTextLength=GetWindowTextLength(hwndEditOut);
SendMessage(hwndEditOut,EM_SETSEL,nTextLength,-1);
SendMessage(hwndEditOut,EM_REPLACESEL,1,(LPARAM)pch);
}
//执行Lu源程序时,仅对无参表达式做计算,以下函数用于输出表达式的结果
void _stdcall OutLuData(LuData *LD)
{
wchar_t wchNum[32],*pStr;
char chNum[32];
int i;
luVOID k=0;
luMessage pMessage; //输出动态库信息的函数,例如本例中定义的LuMessage即是这样的函数
//获取注册到Lu系统的输出动态库信息的函数,通常即本例中定义的LuMessage函数,但也不一定
pMessage=(luMessage)SearchKey((char *)&k,sizeof(luVOID),luPubKey_User);
if(!pMessage) return;
switch(LD->VType)
{
case luStaData_nil:
pMessage(L"nil");
break;
case luStaData_int64:
_i64tow_s(LD->x,wchNum,22,10);
pMessage(wchNum);
break;
case luStaData_double:
_gcvt_s(chNum,*(double *)&(LD->x),16);
for(i=0;chNum[i];i++) wchNum[i]=chNum[i];
wchNum[i]='\0';
pMessage(wchNum);
break;
case luStaData_complex:
pMessage(L"(");
_gcvt_s(chNum,*(double *)&(LD->x),16);
for(i=0;chNum[i];i++) wchNum[i]=chNum[i];
wchNum[i]='\0';
pMessage(wchNum); pMessage(L",");
_gcvt_s(chNum,*(double *)&(LD->y),16);
for(i=0;chNum[i];i++) wchNum[i]=chNum[i];
wchNum[i]='\0';
pMessage(wchNum); pMessage(L")");
break;
case luStaData_vector:
pMessage(L"(");
_gcvt_s(chNum,*(double *)&(LD->x),16);
for(i=0;chNum[i];i++) wchNum[i]=chNum[i];
wchNum[i]='\0';
pMessage(wchNum); pMessage(L",");
_gcvt_s(chNum,*(double *)&(LD->y),16);
for(i=0;chNum[i];i++) wchNum[i]=chNum[i];
wchNum[i]='\0';
pMessage(wchNum); pMessage(L",");
_gcvt_s(chNum,*(double *)&(LD->z),16);
for(i=0;chNum[i];i++) wchNum[i]=chNum[i];
wchNum[i]='\0';
pMessage(wchNum); pMessage(L")");
break;
case luStaData_logical:
if(LD->x)
pMessage(L"true");
else
pMessage(L"false");
break;
case luStaData_string:
case luDynData_string:
pStr=GetStr(LD,NULL,k);
if(pStr) pMessage(pStr);
break;
default:
pMessage(L"\r\n不可识别类型!\r\n");
}
pMessage(L"\r\n");
}
bool LoadMLu(void) //加载MLu
{
if(!InitMLu()) return false;
LoadDll(AllDllName); //加载Lu扩展动态库
return true;
}
void comcode(void) //将Lu源代码编译为模块
{
wchar_t *pstr=NULL;
int nCode,nTextLength,k;
luINT err1,err2;
int ErrType; //运行错误类型
wchar_t *FunName; //出错函数名
void *ForHandle; //运行出错的表达式句柄
luVOID m=0;
wchar_t *ppErrStrS[]=
{
L"\r\n编译错误:递归调用指定的模块。\r\n",//-7
L"\r\n编译错误:找不到指定的模块。\r\n",//-6
L"\r\n编译错误:缺少模块名。\r\n",//-5
L"\r\n编译错误:注释符号/* ... */不成对。\r\n",//-4
L"\r\n编译错误:未使用模块编译功能,不能编译指定的模块。\r\n",//-3
L"\r\n编译错误:无法加锁模块。\r\n",//-2
L"\r\n编译错误:未用。\r\n",//-1
L"\r\n编译错误:编译成功。\r\n",//000000000000
L"\r\n编译错误:内存分配失败。\r\n",//1
L"\r\n编译错误:括号不成对。\r\n",//2
L"\r\n编译错误:(等号后)没有表达式。\r\n",//3
L"\r\n编译错误:非法的函数句柄。\r\n",//4
L"\r\n编译错误:字符串中转义字符错误。\r\n",//5
L"\r\n编译错误:字符串无效,即\"...\"不匹配。\r\n",//6
L"\r\n编译错误:不可识别字符。\r\n",//7
L"\r\n编译错误:表达式名称定义错误。\r\n",//8
L"\r\n编译错误:不可识别的自变量,自变量只能以字母或下画线开头。\r\n",//9
L"\r\n编译错误:不可识别的自变量定义方法,“(,:,:,:,:,...)”冒号过多。\r\n",//10
L"\r\n编译错误:自变量定义错误。\r\n",//11
L"\r\n编译错误:continue()函数只能有0个参数。\r\n",//12
L"\r\n编译错误:只能在while,until中使用continue函数。\r\n",//13
L"\r\n编译错误:break()函数只能有0个参数。\r\n",//14
L"\r\n编译错误:只能在while,until中使用break函数。\r\n",//15
L"\r\n编译错误:if,while,until,which中的参数个数至少为2个。\r\n",//16
L"\r\n编译错误:表达式中的数字错误。\r\n",
L"\r\n编译错误:&单目取地址运算符只能用于单独的变量。\r\n",
L"\r\n编译错误:单目运算符++、--错误。\r\n",
L"\r\n编译错误:括号内没有数字。\r\n",
L"\r\n编译错误:单目运算符+、-、!、!!错误。\r\n",
L"\r\n编译错误:赋值“=”错误。\r\n",
L"\r\n编译错误:不正确的运算方式或其他语法错误。\r\n",
L"\r\n编译错误:不可识别变量名。\r\n",
L"\r\n编译错误:不可识别函数名。\r\n",
L"\r\n编译错误:一级函数只能有一个参数。\r\n",
L"\r\n编译错误:二级函数参数不匹配。\r\n",
L"\r\n编译错误:关键字Static或Common的位置非法。\r\n",
L"\r\n编译错误:(模块中)表达式有重名。\r\n",
L"\r\n编译错误:对形如“-2^3”的式子,须用括号给前置单目运算符“-”和乘方运算符“^”(或点乘方运算符“.^”)指出运算顺序。\r\n",
L"\r\n编译错误:类成员运算符后只能是变量名、字符串、括号运算符或者类成员函数。\r\n",
L"\r\n编译错误:后单目运算符'、.'错误。\r\n",
L"\r\n编译错误:调用表达式时参数不匹配。\r\n",
L"\r\n编译错误:未使用。\r\n",
L"\r\n编译错误:自变量重名。\r\n",
L"\r\n编译错误:因检测到运行错误而退出。\r\n",//36
L"\r\n编译错误:未使用。\r\n",
L"\r\n编译错误:未使用。\r\n",
L"\r\n编译错误:表达式太长或表达式中字符串太多。\r\n",//39
L""
};
nTextLength=GetWindowTextLength(hwndEditCode)+1;
pstr=new wchar_t[nTextLength];
if(!pstr) return;
GetWindowText(hwndEditCode,pstr,nTextLength);
k=UseLu(2); //申请进入Lu工作区,保证了多线程程序中,互斥使用Lu系统
if(!k) //进入Lu工作区
{
DelModule(hModule); //销毁以前编译的模块
GetRunErr(ErrType,FunName,nCode,ForHandle); //设置运行错误为无错状态
//注册LuMessage函数到Lu系统,使Lu运行时可输出函数信息
//其他Lu扩展库也可注册类似的函数到Lu系统,故每次编译前都进行注册
InsertKey((char *)&m,sizeof(luVOID),luPubKey_User,LuMessage,NULL,NULL,0,ForHandle);
nCode=ComModule(pstr,nModule,hModule,err1,err2); //编译模块
UseLu(0); //离开Lu工作区
if(nCode) //有编译错误
{
hModule=NULL;
nTextLength=GetWindowTextLength(hwndEditOut);
SendMessage(hwndEditOut,EM_SETSEL,nTextLength,-1);
if(nCode>=-7&&nCode<=39) SendMessage(hwndEditOut,EM_REPLACESEL,1,(LPARAM)ppErrStrS[nCode+7]);
nTextLength=GetWindowTextLength(hwndEditCode);
if(err1>=0&&err1<=nTextLength&&err2>=0&&err2<=nTextLength)
{
SendMessage(hwndEditCode,EM_SETSEL,err1,err2+1);
SetFocus(hwndEditCode);
}
}
}
else if(k==1)
{
LuMessage(L"\r\n同一线程不能同时使用Lu工作区!无法编译程序!请稍后再试!\r\n");
}
delete[] pstr;
}
//////////////////////////////////////// Windows应用程序入口
int WINAPI WinMain(HINSTANCE hhInstance,HINSTANCE hPrevInst,LPSTR lpszCmdLine,int nCmdShow)
{
HWND hWnd;
MSG Msg ;
WNDCLASS wndclass ;
wchar_t lpszClassName[]=L"classTestMLu";//窗口类名
wchar_t lpszTitle[]= L"TestMLu"; //窗口标题名
hInstance=hhInstance; //记住实例句柄
//窗口类的定义
wndclass.style = 0; //窗口类型
wndclass.lpfnWndProc = WndProc ; //窗口处理函数为WndProc
wndclass.cbClsExtra = 0 ; //窗口类无扩展
wndclass.cbWndExtra = 0 ; //窗口实例无扩展
wndclass.hInstance = hInstance ; //当前实例句柄
wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION) ;//窗口的最小化图标为缺省图标
wndclass.hCursor = LoadCursor( NULL, IDC_ARROW) ;//窗口采用箭头光标
wndclass.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH) ;//窗口背景为白色
wndclass.lpszMenuName = L"mainMenu" ; //窗口菜单
wndclass.lpszClassName = lpszClassName ; //窗口类名
//窗口类注册
if( !RegisterClass( &wndclass)) //如果注册失败则发出警告声音
{
MessageBeep(0) ;
MessageBox(GetFocus(),L"注册失败!",L"TestMLu",MB_OK);
return 0;
}
//创建窗口
hWnd=CreateWindow(lpszClassName, //窗口类名
lpszTitle, //窗口实例的标题名
WS_OVERLAPPEDWINDOW,//窗口的风格
CW_USEDEFAULT,
CW_USEDEFAULT, //窗口左上角坐标为缺省值
CW_USEDEFAULT,
CW_USEDEFAULT, //窗口的高和宽为缺省值
NULL, //此窗口无父窗口
NULL, //此窗口无主菜单
hInstance, //创建此窗口的应用程序的当前句柄
NULL) ; //不使用该值
//显示窗口
ShowWindow( hWnd, SW_SHOWNORMAL) ;
//绘制用户区
UpdateWindow(hWnd);
LoadMLu(); //加载MLu
//消息循环
while( GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage( &Msg) ;
DispatchMessage( &Msg) ;
}
if(!UnregisterClass(lpszClassName,hInstance))// Are We Able To Unregister Class
{
MessageBox(NULL,L"Could Not Unregister Class.",L"TestMLu",MB_OK | MB_ICONINFORMATION);
}
FreeMLu(); //释放MLu
return Msg.wParam; //消息循环结束即程序终止时将信息返回系统
}
//窗口函数
LRESULT CALLBACK WndProc(HWND hWnd,UINT Message,WPARAM wParam, LPARAM lParam)
{
int k;
void *v;
luVOID m=0;
switch(Message)
{
case WM_CREATE:
hwndEditCode=CreateWindow(L"EDIT",NULL, //创建代码编辑框;
WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|WS_BORDER|ES_LEFT|ES_MULTILINE|
ES_AUTOHSCROLL|ES_AUTOVSCROLL,
0,0,LOWORD(lParam),HIWORD(lParam/2),hWnd,(HMENU)IDE_EditCode,hInstance,NULL);
hwndEditOut=CreateWindow(L"EDIT",NULL, //创建输出编辑框;
WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|WS_BORDER|ES_LEFT|ES_MULTILINE|
ES_AUTOHSCROLL|ES_AUTOVSCROLL,
0,HIWORD(lParam/2+2),LOWORD(lParam),HIWORD(lParam/2-2),hWnd,(HMENU)IDE_EditOut,hInstance,NULL);
SetWindowText(hwndEditCode,L"//这里是代码窗口,请将Lu代码写在下面\r\n");
SetFocus(hwndEditCode);
break;
case WM_SIZE:
MoveWindow(hwndEditCode,0,0,LOWORD(lParam),HIWORD(lParam/2),true);
MoveWindow(hwndEditOut,0,HIWORD(lParam/2+2),LOWORD(lParam),HIWORD(lParam/2),true);
UpdateWindow(hWnd);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDM_cal_com:
comcode(); //编译模块
break;
case IDM_cal_cal:
k=UseLu(2); //申请进入Lu工作区
if(!k) //申请Lu工作区
{
//注册LuMessage函数到Lu系统,使Lu运行时可输出函数信息
//其他Lu扩展库也可注册类似的函数到Lu系统,故每次计算前都进行注册
InsertKey((char *)&m,sizeof(luVOID),luPubKey_User,LuMessage,NULL,NULL,0,v);
if(hModule) ExeModule(hModule,OutLuData); //执行模块
UseLu(0); //离开Lu工作区
}
break;
case IDM_cal_comcal:
comcode(); //编译模块
k=UseLu(2); //申请进入Lu工作区
if(!k) //申请Lu工作区
{
//注册LuMessage函数到Lu系统,使Lu运行时可输出函数信息
InsertKey((char *)&m,sizeof(luVOID),luPubKey_User,LuMessage,NULL,NULL,0,v);
if(hModule) ExeModule(hModule,OutLuData); //执行模块
UseLu(0); //离开Lu工作区
}
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0); //调用PostQuitMessage发出WM_QUIT消息
break;
default: //默认时采用系统消息默认处理函数
return DefWindowProc(hWnd,Message,wParam,lParam);
}
return 0;
}
16、在工程中打开“TestMLu.cpp”文件,已加入了Lu脚本支持代码。
17、从软件包http://www.forcal.net/xiazai/lu1/lu32.rar中找到 lu32.dll、MLu32.dll、lu32.lib、MLu32.lib、C++格式的头文件lu32.h,复制到以下文件夹。
18、重新“生成->生成解决方案”。
19、重新运行程序,弹出几个“MLu:加载动态库失败”的窗口。
20、运行一段代码,OK!
21、打开文件夹 D:\lu\lu32\TestMLu\Debug
22、双击运行“TestMLu.exe”。
23、将“lu32.dll”和“MLu32.dll”复制到该文件夹。
24、再双击运行“TestMLu.exe”,和前面一样,弹出几个“MLu:加载动态库失败”的窗口,但可以运行Lu程序。
Lu程序及运行结果:
25、从软件包http://www.forcal.net/xiazai/lu1/lu32.rar中找到文件夹“dll”,该文件夹中包含了若干Lu扩展动态库,将整个文件夹复制到这里。
26、再次双击运行“TestMLu.exe”,程序顺利启动。
27、运行一段OpenLuGl代码。
28、下载工程TestMLu(不包含文件夹“dll”):http://www.forcal.net/bczl/luc/SDKTestMLu.rar。
29、如果希望得到一个语法高亮的编辑器,可下载(不包含文件夹“dll”):http://www.forcal.net/bczl/luc/RICHEDTestMLu.rar。
RICHEDTestMLu是在SDKTestMLu的基础上生成的,使用了Richedit控件。比较一下RICHEDTestMLu和SDKTestMLu中的TestMLu.cpp文件,可以了解做了哪些更改。
注意RICHEDTestMLu中添加了三个语法高亮的关键字 while、if、new,你可以修改代码以增加更多的语法高亮关键字。
由于RICHEDTestMLu中的TestMLu.cpp文件较长,故本文未提供,可在TestMLu.cpp中查找字符串Richedit了解新增的代码部分。