在Win32 SDK中使用Lu模块化编译运行库MLu

时间:2022-10-11 09:06:21

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 2008VC++ 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.hTestMLu.rcTestMLu.cpp三个文件放到文件夹“D:\lu\lu32\TestMLu\TestMLu”。


 

9、返回VC,点击下图中红色圈出部分“项目->添加现有项”。

10、添加TestMLu.hTestMLu.rcTestMLu.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.dllMLu32.dlllu32.libMLu32.libC++格式的头文件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控件。比较一下RICHEDTestMLuSDKTestMLu中的TestMLu.cpp文件,可以了解做了哪些更改。

注意RICHEDTestMLu中添加了三个语法高亮的关键字 whileifnew,你可以修改代码以增加更多的语法高亮关键字。

由于RICHEDTestMLu中的TestMLu.cpp文件较长,故本文未提供,可在TestMLu.cpp中查找字符串Richedit了解新增的代码部分。